Arduino: Bitgehäcksle...

z.B. wxWidgets, GTK+, Qt, OpenGL, DirectX
Antworten
Onraku
Beiträge: 43
Registriert: Fr Sep 09, 2011 2:14 pm

Arduino: Bitgehäcksle...

Beitrag von Onraku » Mi Dez 26, 2012 9:24 pm

Ich hab mir ein ganz einfaches Problem gestellt und gelöst, und der Transfer zur nächsten Stufe will mir nicht gelingen...
Vielleicht ist ja hier der ein oder andere cloidnerux hier der mir weiterhelfen kann... ;)

Folgender Code funktioniert schon.
Es soll aus einem Taster einen Schalter machen:

Code: Alles auswählen

//SinglePinTastSchalter
byte state = LOW;      //derzeitiger LED-Zustand, 
byte reading;          //derzeitiger Taster-Zustand
byte previous = HIGH;  //letzter Taster-Zustand

long time = 0;
long debounce = 200;

void setup()
{
  pinMode(14, INPUT_PULLUP);  //=A0 mit internem 2k-Pullup  (pin14->taster->GND)
  pinMode(2, OUTPUT);         //=D2             (pin2->LED->GND)
  
}


void loop()
{
  reading = digitalRead(14);    //Taster einlesen
  if (reading==HIGH && previous==LOW && millis()-time > debounce)
              //reading==1 && previous==0 ->Taster gedrückt
              //millis()-time > debounce  ->und entprellt
  {
    if (state==HIGH)      //ändere LED-Zustand
      state=LOW;
    else
      state=HIGH;
      
    time = millis();      //Wartezeit für nächsten Schleifendurchlauf nullen
  }
  digitalWrite(2, state); //LED schalten
  previous = reading;     //letzter Input=aktueller Input
}
Da ich später ein paar Taster mehr brauche, und meine Zustandsvariablen reading, previous und state nicht zu arrays machen will, habe ich versucht ein einzelnes Bit zu betrachten.
state kann sich nur ändern wenn reading==HIGH && previous==LOW && (millis()-time > debounce)==TRUE.
(millis()-time > debounce) speicher ich in byte t.
Alle anderen Wertequatrupel bewirken, dass state bleibt wie es ist.
Aus reading, previous, state und t ergibt sich eine 16reihige Wertetabelle die mit dem Zielwert (aktualisierte state-Variable) ausgefüllt werden kann.
Mit einem KV-Diagramm lässt sich das "kürzen" zu:

Code: Alles auswählen

 if ((!reading&&state)||(!previous&&state)||(!t&&state)||(reading&&previous&&!state&t));
     aktuellerState==HIGH;
 else aktueller==LOW;
Die if-Bedingung liefert ja nur 1 oder 0, daher die kürzere Version unten im Quelltext.

Code: Alles auswählen

//SinglePinTastSchalter_bitwise
byte state = LOW;
byte reading;
byte previous = HIGH;
byte t;                                      //für (millis()-time > debounce)

unsigned long time = 0;
unsigned long debounce = 200;

void setup()
{
  pinMode(14, INPUT_PULLUP);
  pinMode(2, OUTPUT);
}


void loop()
{
  
  reading = digitalRead(14);
  if((millis()-time) > debounce)
    t=1;
  else t=0;
 
  state=((~reading&state)|(~previous&state)|(~t&state)|(reading&previous&~state&t));
  
 
  time = millis();
  
  digitalWrite(2, state);  
  previous = reading;
}
Kürzen ist vielleicht das falsche Wort, das sieht gerade viel komplizierter aus als vorher. Ich möchte mit den Bit-Operatoren später ganze Bytes bzw. 4 Bytes verarbeiten, und was mit einem Bit geht sollte ja auch mit mehreren gehen. Zumal eine Implementierung mit Arrays den Nachteil hat, dass ich mit for-Scheifen alle Taster nacheinander auslesen muss. Im Bitmode könnte ich ganze Bytes als Port mit 8 Pins auf einmal einlesen.
Ich habe mal alle Variablen und "Argumente"der Logik-Funktion überwacht und festgestellt, dass alle Werte der Erwartung entsprechen, nur die Neuzuweisung von state klappt nicht, womit state immer LOW bleibt. Aber warum will ich einfach nicht verstehen...

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3081
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: Arduino: Bitgehäcksle...

Beitrag von cloidnerux » Mi Dez 26, 2012 10:36 pm

Ich hab mir ein ganz einfaches Problem gestellt und gelöst, und der Transfer zur nächsten Stufe will mir nicht gelingen...
Vielleicht ist ja hier der ein oder andere cloidnerux hier der mir weiterhelfen kann...
Schauen wir mal.
Mit einem KV-Diagramm lässt sich das "kürzen" zu:
So weit bin ich auf einem AVR noch nie gegangen, aber gut.
Ich möchte mit den Bit-Operatoren später ganze Bytes bzw. 4 Bytes verarbeiten
Beachte: DU bist hier auf einer 8-Bit Plattform, du solltest Variablen größer 8-Bit wenn es geht vermeiden, das kostet nur Platz und Laufzeit.
Ich habe mal alle Variablen und "Argumente"der Logik-Funktion überwacht und festgestellt, dass alle Werte der Erwartung entsprechen, nur die Neuzuweisung von state klappt nicht, womit state immer LOW bleibt. Aber warum will ich einfach nicht verstehen...
Wo und wie hast du die Werte überwacht?

Zudem gehst du das Problem zu Kompliziert an. Wenn du mehrere Bits erreichen willst, ist dein Ansatz viel zu kompliziert. Wenn ich es richtig verstehe, willst du immer zwischen zwei States toggeln, also von Low->High, High->Low. Das kannst du Binär mit der Invertierung lösen.

Code: Alles auswählen

state = ~state;
Wenn du nur ein einziges Bit toggeln willst:

Code: Alles auswählen

state = (state & ~(1<< bitPos)) | (~state & (1 << bitPos))
Damit fallen deine Hilfsvariablen previous, reading und t weg.

Dann ist deine Entprellung falsch. Nur warten nutzt dir Nix, dann bekommst du ein falsches Ergebnis nur zu einer anderen zeit. Du musst dir merken, in welchem Zusand der Taster vor der Wartefrist war. Also Wert lesen, warten, lesen, vergleichen.
Dann ergibt sich der Rest zu:

Code: Alles auswählen

taster entprellen...
if(taster1 == 1)
{
    state = (state & ~(1<< bitPos)) | (~state & (1 << bitPos));
    //Sichergehen das du nicht bei jedem durchlauf durch loop toggelst!
    taster1 = 0;
}
Generell gilt auf AVRs: Generisch und einfach programmieren! Komplizierte und tolle Code-Konstrukte können viel ausmachen. Ich hatte mal auf einem tiny13 zwei Codes die genau das gleiche machten, aber 800% unterschied in der Größe hatten, was bei maximal 1k Code nicht toll war.
Auf einem Atmega328 habe ich gemerkt, dass Ring-Cyclen mit dem Modulo sehr viel langsamer sind als einfach ein if das prüft.
Ist so eine eigene Welt^^
Redundanz macht wiederholen unnötig.
quod erat expectandum

Onraku
Beiträge: 43
Registriert: Fr Sep 09, 2011 2:14 pm

Re: Arduino: Bitgehäcksle...

Beitrag von Onraku » Do Dez 27, 2012 2:40 pm

Danke schonmal für die Antwort:
Wo und wie hast du die Werte überwacht?
Per serialout alle Variablen ausgegeben, hab das aus dem geposteten Quelltext genommen um ein bisschen Übersicht zu wahren.

Argh, jetzt ist Kaffee und Kuchen angesagt... Schau mir das später nochmal in Ruhe an...

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3081
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: Arduino: Bitgehäcksle...

Beitrag von cloidnerux » So Jan 06, 2013 3:44 pm

Mir ist gerade eingefallen, dass das toggeln von Bits deutlich einfacher mit XOR geht.
Durch

Code: Alles auswählen

A XOR 0 = A
und 
A XOR 1 = !A
Kann man ein Bit in einem byte durch

Code: Alles auswählen

State = State ^ (1 << BitPos);
toggeln, wobei BitPos(0-7) die Position des Bits in der Variable ist.
das dürfte man egt auch so schreiben dürfen:

Code: Alles auswählen

State ^= (1 << BitPos);
MfG cloidnerux.
Redundanz macht wiederholen unnötig.
quod erat expectandum

Antworten