Schalter als BCD Code auswerten

Hallo zusammen,

ich baue gerade für meinen Neffen eine Nachttisch Lampe mit 40 WS2812. Die Lampe hat vier Drehpotis und vier Kippschalter. Mit den Kippschaltern sollen verschiedene Programme angewählt werden können. Als Beispiel Programm 0, alle LEDs an, und Poti Nr.1 regelt die Helligkeit. Programm Nr. 1 Poti Nr. 1 Regelt die Helligkeit, Poti 2 rot, Poti 3 grün, Poti 4 blau. Programm 3 dann wieder was anderes. Die Auswertung der Schalter in Programmnummern habe ich mir bisher so gedacht:

if (SCHALTER1 == HIGH){
BCD1 = 0;
}
else {
BCD1 = 1;
}
if (SCHALTER2 == HIGH){
BCD2 = 0;
}
else {
BCD2 = 2;
}
if (SCHALTER4 == HIGH){
BCD4 = 0;
}
else {
BCD4 = 4;
}
if (SCHALTER8 == HIGH){
BCD8 = 0;
}
else {
BCD8 = 8;
}
byte PROGNO = BCD1 + BCD2 + BCD4 + BCD8;

Gibt es einen eleganteren Weg, so dass ich mit den Schaltern direkt die Bits im byte PROGNO beeinflussen kann? Wie würdet Ihr di einzelnen Programme ausführen? Mit else if?

Grüße und danke,

Sven

Du hängst die Schalter an Pins die zu einem Port gehören. Siehe hier:
http://www.pighixxx.com/pgdev/Temp/Arduino_uno_Pinout_Web.png

z.B. Pins 8-11 entsprechen Port B, Pins 0-3

Dann kannst du einfach das machen:

byte value = PINn & 0x0F;

Wobei n der Buchstabe des Ports ist. Wenn die Pins nicht 0-3 sind, sondern z.B. 2-5 kann man vor dem verUNDen zwei mal (oder mehr) schieben um sie auf die niederwertigen 4 Bit zu bekommen.

EDIT:
Das Eingangs-Register ist PINn. PORTn ist das Ausgangs-Register. Oops

Hier mehr dazu:

Danke! Das ist genau das was ich gesucht habe. Ist etwas eleganter wie mein Zeug.

Grüße,

Sven

Es gibt übrigens fertige BCD Schalter:

http://such002.reichelt.de/index.html?ACTION=3;ARTICLE=9433;SEARCH=KMR%2010

Ganz so einfach ist es dann doch nicht. Wie bringe ich jetzt das Value dazu, den Wert der Pins 12 und 13 zu ignorieren, bzw wie kann ich jedes einzelne Bit "umdrehen", dann kann ich nämlich alle Eingänge mit Pullup auf High ziehen, da die restlichen Pins eh frei sind. Und was passiert mit den zwei bits, die zu einem Byte noch fehlen? So ganz verstehe ich das alles noch nicht. Wenn mir da jemand Licht ins Dunkel bringen könnte wäre das super.
Ich habe bewusst keinen Drehschalter oder sonstwas genommen, weil der Junge so ganz nebenbei das binäre Zahlensystem lernt.

edit: Nachdem ich einem Link in Deinem Link gefolgt bin wird es jetzt langsam heller. Hier wird das alles genau erklärt: Arduino Playground - BitMath
Grüße,

Sven

Du solltest dich vielleicht mal mit boolescher Algebra beschäftigen. Dafür ist das & 0x0F da.

z.B: 10101011 & 0x0F (00001111) = 00001011

Setzt das obere Nibble (Halbbyte) auf 0

Invertieren geht mit einem XOR:

00001001 ^ 0x0F = 00000110

Und was passiert mit den zwei bits, die zu einem Byte noch fehlen?

PB6 und PB7 sind auch die Pins an denen der Oszillator angeschlossen ist. Es kann also sein, dass man da irgendwelche Werte ausliest. Auch da hilft das UND wenn die nicht immer 0 sind.

Hallo, ein Tipp noch am Rande für die Nachttischlampe. Du kannst anstatt 4 Potis für
Helligkeit, Rot, Grün, Blau auch 3 Potis verwenden für Farbton, Sättigung und Helligkeit :wink:

Das mit den vier Potis ist schon so beabsichtigt, weil sich Farben leichter hell einstellen lassen, und dann dimmen, als gleich relativ dunkel einstellen. Aber das ist wohl Geschmackssache. Wenn ich meine Pins mit dem internen Pullup widerstand auf High ziehe, und geschaltet dann low ist, dann sollte doch folgendes das richtige ergeben:

TEMPWERT = PINB | 0xF0;
PROGNO = TEMPWERT ^ 0xFF;

Oder?

Grüße,

Sven

Geht auch in einer Zeile:

PROGNO = PINB & 0x0F ^ 0x0F;

Das wird dann von links nach rechts abgearbeitet

0x0F wenn du an Pins 0-3 hängst. 0xF0 wäre für Pins 4-7. Und auch beim XOR nur 0x0F. Mit 0xFF invertierst du auch die Bits an deinen keine Schalter hängen! Durch das vorherige UND wäre dann das obere Nibble immer 1111. Ich glaube das ist nicht was du willst, wenn du die Schaltstellungen als Dezimalzahlen betrachten willst.

Übrigens schreibt man eigentlich nur Konstanten komplett groß. Nicht normale Variablen

EDIT:
Sehe jetzt, dass du da einer ODER hattest. Das geht dann so. Ist aber etwas verwirrend wenn man den Standard-Weg gewöhnt ist. Normalerweise maskiert man nicht benötigte Bits mit einem UND aus. Das ODER funktioniert da nur wegen dem XOR danach. UND geht immer.

Vielen Dank, dann halte ich mich wohl an den Standard Weg, das macht dann das Fehlersuchen einfacher, wenn man andere Leute wie hier im Forum hinzu zieht. Auch meine PROGNO heißt jetzt ProgNo.
Es funktioniert übrigens so wie von Dir geschrieben einwandfrei.

Grüße,

Sven

edit: Für diese tolle Hilfe gab es auch etwas Karma von mir. Danke nochmal

:slight_smile:

Dein erster Versuch wäre übrigens auch hiermit einfacher gegangen:
http://arduino.cc/en/Reference/BitWrite

Damit kann man das machen:

byte progNo = 0;
bitWrite(progNo, 0, (SCHALTER1 == HIGH));
bitWrite(progNo, 1, (SCHALTER2 == HIGH));
bitWrite(progNo, 2, (SCHALTER3 == HIGH));
bitWrite(progNo, 3, (SCHALTER4 == HIGH));

Länger ist die Musterlösung aber auch nur 5 Zeilen. Und die Invertierung geht wenn man HIGH durch LOW ersetzt.

bitWrite kannte ich auch noch nicht. Ich muss mir mal einen Spickzettel suchen, oder falls ich keinen finde selber erstellen, der den kompletten Befehlssatz der Arduino Software enthält.
Danke,

Sven

Siehe hier:

Außerdem gibt es noch die AVR libc, die von den Arduino Machern gerne versteckt wird:
http://www.nongnu.org/avr-libc/user-manual/modules.html

Hier gibt ist vor allem string.h, stdlib.h und math.h im Alltag relevant (und sind im Hintergrund automatisch inkludiert). Der größte Teil des Rests wird von der Arduino Software ausreichend abstrahiert. sleep.h und power.h braucht man für Energiesparen und wtd.h für den Watchdog Timer, aber das wird eher selten verwendet.

Zuerst: Da SCHALTER1 bereits 0 oder 1 ist braucht es den Vergleich nicht sondern funktioiert ohne diesen.

bitWrite(progNo, 0, (SCHALTER1 == HIGH)); 
bitWrite(progNo, 0, SCHALTER1);

Zweitens: müßte das nicht auch funktionieren?

progNo = SCHALTER1 + SCHALTER2<<1 + SCHALTER3<<2 + SCHALTER4<<3;

http://arduino.cc/en/Reference/Bitshift

Grüße Uwe

Mhh, Moment mal, muss da nicht in beiden Fällen digitalRead() gemacht werden? Fällt mir es jetzt auf. Das sind ja sonst nur Pin-Nummern.

Ansonsten, ja, schieben würde auch gehen. :slight_smile:

Serenifly:
Mhh, Moment mal, muss da nicht in beiden Fällen digitalRead() gemacht werden? Fällt mir es jetzt auf. Das sind ja sonst nur Pin-Nummern.

Ich habe angenommen daß es im nicht übermittelten Teil des Sketches gemacht wird. 8)
Grüße Uwe

Ich kann jetzt sagen, dass folgende Lösung auf alle Fälle geht:

PROGNO = PINB & 0x0F ^ 0x0F;

Da ich frei in der Pinwahl bin geht das so. Habe ich gerade ausprobiert..
Bitwrite und Bitshift werden auf alle Fälle im Hinterkopf notiert, da kommt bestimmt noch eine Anwendung, wo ich das brauchen kann.
Ach ja, wegen der Librarys, die sind auch sehr interessant. Da finde ich bestimmt noch einiges.
Danke Euch beiden.