Pages: [1]   Go Down
Author Topic: Arduino-Keyboard  (Read 757 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo!

Ich hab folgendes vor: Mit 12 Tastern und einem Piezo-Buzzer möchte ich mir ein kleines 1-Oktav-Keyboard basteln. Mit der Tone-Funktion kann man ja ganz einfach bestimmte Töne erzeugen. Daher dachte ich mir, dass das eigentlich relativ leicht zu coden sein müsste, jetzt habe ich aber ein komisches Problem:

Ich hab die Schaltung für einen Taster auf dem Breadboard augebaut. Schreibe ich den Code für einen einzigen Taster, ist alles in Ordnung. Schreibe ich jedoch den Code für den 2. Taster (siehe auskommentiertes) dazu, verursacht der Piezo-Buzzer mit dem selben ersten Taster einen anderen (viel zu hohen) Ton. D.h. der zusätzliche Code hat irgendwie einen Einfluss auf den Codeteil der davor einwandfrei funktioniert hat. Wie kann das sein? Hat da vielleicht jemand eine Idee? Steh gerade irgendwie aufm Schlauch...:/

Code:
int speakerPin = 9;
int taster1 = 2;
int taster2 = 3;

void setup() {
 pinMode(speakerPin, OUTPUT);
 pinMode(taster1, INPUT);
 pinMode(taster2, INPUT);
 digitalWrite(taster1, HIGH);  // pullup-Widerstände
 digitalWrite(taster2, HIGH);

}
void loop() {
  if (digitalRead(taster1) == LOW) {
    tone(speakerPin, 400);
  }
  else {
    noTone(speakerPin);
  }
//    if (digitalRead(taster2) == LOW) {
//    tone(speakerPin, 500);
//  }
//  else {
//    noTone(speakerPin);
//  }
  }
Logged

Offline Offline
Newbie
*
Karma: 1
Posts: 30
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Servus,

Wenn du z.B. den 2. button drückst:
Im ersten if kommst du immer in den else-zweig mit notone, im zweiten if in den tone-teil.
Das schaltet den piezo ganz schnell an und aus und an und aus und ... Naja smiley-wink

Notone willst du nir machen, wenn KEIN Button gedrueckt wird.
Logged

Forum Moderator
BZ (I)
Offline Offline
Brattain Member
*****
Karma: 236
Posts: 20298
+39 349 2158303
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Für die Erklärung von -Holger- hab ich etwas gebraucht um es zu verstehen.

Jede nicht gedrückte Taste schaltet den Ton sofort wieder aus, weil im else Teil noTone(speakerPin); steht.
Du mußt die Tastaturkontrolle auf Zustandsänderung umschreiben und beim Drücken eines Tasters den Ton einschalten und beim loslassen den Ton ausschalten.

Grüße Uwe
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

aaah ja ich verstehe was ihr meint, daran habe ich gar nicht gedacht. Dann wird der Code wohl doch ein kleines bisschen aufwändiger smiley-wink

Vielen Dank euch beiden!
Logged

Offline Offline
Edison Member
*
Karma: 21
Posts: 1407
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Kleiner Vorschlag, um Deinen Code zu vereinfachen. Du kannst ja Deine 12 Taster an die Pins 2 bis 13 anschliessen, dann bleiben 0 und 1 für die serielle Schnittstelle frei. Zusätzlich würde ich die Taster "LOW-aktiv" verwenden, also mit dem internen PullUp Widerstand, damit sparst Du dir die Widerstände an den Tastern. Die Taster schalten dann das Pin gegen Masse und liefern ein HIGH wenn sie nicht gedrück sind und ein LOW wenn sie gedrückt wurden.

Die Pins 0 bis 7 werden durch den PORTD abgebildet, auf den man direkt zugreifen kann. Ebenso die Pins 8 bis 13, die durch den PORTB abgebildet werden. Siehe http://www.arduino.cc/en/Reference/PortManipulation
mit einem
Code:
unsigned int input =(( PORTD & 0x3F ) << 8) + ( PORTB & 0xFC );
Bekommst Du einen 16 bit Wert der alle gedrückten Taster repräsentiert. In einem switch() - case Block kannst Du das dann super auswerten.
Was macht die o.g. Zeile:
unsigned int definert eine vorzeichenlose 16bit Zahl
( PORTD & 0x3F ) << 8 ) liest den kompletten PORTD (Pin 8 bis 13) aus und blendet die obersten zwei Bits aus, da die keine Input-Pin Daten enthalten und mit dem "& 0x3F" sicher auf 0 gesetzt werden. Anschliessend wird mittles Bit-Shift der Wert um 8 Bit nach links geschoben.
+ ( PORTB & 0xFC ); hier wird der Port B (Pin 0 bis 7) ausgelesen und durch das & 0xFC die untersten beiden Bits (Pin 0 und 1) ausgeblendet. Dieser Wert wird zum vorherigen Wet addiert, also in den untersten 8 Bit des 16 bit Wertes eingefügt.
« Last Edit: December 31, 2012, 08:51:15 am by mkl0815 » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

wow ok das muss ich mir erstmal in Ruhe durchlesen und verstehen smiley-wink
danke für den Tip!
Logged

Offline Offline
Edison Member
*
Karma: 21
Posts: 1407
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, kleine Korrektur. Wenn man schon Vorschläge macht, dann wenigstens korrekt  smiley-eek
Die Ports PORTB und PORTD sind die Output-Register und damit für Taster leider kompletter Quark. PINB und PIND sind die passenden Input-Register.
Mit folgendem Programm kann man das Ganze schon mal testen:
Code:

void setup() {
  Serial.begin(9600);
  //Pin 2 bis 13 als Eingang mit aktiviertem PullUp setzen
  for (int i = 2; i<=13; i++)
     pinMode(i,INPUT_PULLUP);
}

void loop() {
  //Alle Eingänge einlesen
  unsigned int input =(( PINB & B00111111 ) << 8) + ( PIND & B11111100 );
 
  Serial.println(input,BIN);
  delay(100);
}
Bei meinem kleinen Duemilanove Clone habe ich leider das Problem mit dem Pin 13 und der daran angeklemmten LED. Diese zieht anscheinen über ihren Vorwiderstand das Pin bereits gegen Masse, daher ist Pin13 immer LOW. Ist das beim Uno auch so? Ich vermute mal ja.
Ansonsten liefert das Testprogramm die binäre Darstellung der Pins 0 bis 13. Zieht man nun eines der Pins auf Masse, sieht man die entsprechende Veränderung in der Ausgabe.

Falls das Pin 13 auch beim Uno ein Problem ist, kann man stattdessen die Pins 0 und 1 mit verwenden. Allerdings hat man dann keine einfache Debugmöglichkeit mehr, da man die serielle Schnittstelle blockiert. Wenn allerdings keine Datem vom PC empfangen werden müssen, kann man einfach das RX (Pin 0) verwenden und auf Pin 1 (TX) trotzdem Ausgaben an den Rechner senden.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ich hoffe du bist mir nicht böse, aber ich habs jetzt erstmal auf "herkömmliche" Weise probiert  smiley-red
werd mich deinem Lösungsansatz aber aufjeden Fall auch mal widmen, habe mich bisher noch nie mit der seriellen Schnittstelle beschäftigt.

hier mal mein code den ich gebastelt habe; funktioniert für 2 Taster wunderbar und sollte dann eigentlich auch für mehrere funktionieren:

Code:
int speaker = 9;
int taster[] = {2, 3};
boolean lastState[] = {false, false};
boolean state[] = {false, false};
int frequencies[] = {400, 500};

boolean tasterCheck(int i) {
  if(digitalRead(taster[i]) == LOW) {
    return true;
  }
  else {
    return false;
  }
}

void setup() {
 pinMode(speaker, OUTPUT);
   for(int i = 0; i < 2; i++){
  pinMode(taster[i], INPUT);
  digitalWrite(taster[i], HIGH);
  }
}


void loop() {
  for(int i = 0; i < 2; i++){
    state[i] = tasterCheck(i);
    if(state[i] != lastState[i]){
      tone(speaker, frequencies[i]);
    }
  lastState[i] = state[i];
  }
 
  if(state[0] == false && state[1] == false){
    noTone(speaker);
  }   
}
Logged

Offline Offline
Edison Member
*
Karma: 21
Posts: 1407
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Wieso sollte ich böse sein? Ich wollte nur eine weitere Möglichkeit aufzeigen, wie man an die Daten der gedrückten Tasten kommt, aber niemanden zwingen meine Lösung zu verwenden.  smiley
Also alles gut! Das Du das Abfragen in einzelne Funktionen gekapselt hast sorgt doch genau so für aufgeräumten Code und wirklich zeitkritisch ist Deine Anwendung auch nicht.
Prost Neujahr,
Mario.
Logged

Pages: [1]   Go Up
Jump to: