Ansteuerung von 4 LEDs mit 5 Tastern und Arduino

Mein Code:

#define MAX 50
const int LED1 = 2;
const int LED2 = 3;
const int LED3 = 4;
const int LED4 = 5;
int array[MAX];
int old_b = 0;
int val;
int counter = 0;
int i;
int temp;
int L1;
int L2;

void setup () {
  pinMode (A5, INPUT_PULLUP);
  Serial.begin(9600);
}

int readButtons (int pin) {
  int b, c;
  c = analogRead(pin);
  Serial.print("analogRead =  ");
  Serial.println(c);
  delay(100);
  if (c > 1015) b = 0;
  else if (c > 70 && c < 76) b = 1;
  else if (c > 122 && c < 128) b = 2;
  else if (c > 169 && c < 175) b = 3;
  else if (c > 209 && c < 217) b = 4;
  else if (c > 247 && c < 256) b = 5;
  else if (c > 280 && c < 291) b = 6;
  else b = 0;
  if (b == old_b) {
   return 0;
   old_b = b;
  } else {
    return b;
    old_b = b;              
    }                           
}

void loop () {
  while ((val = readButtons(5)) != 5) {
    if ((val == 1) || (val == 2) || (val == 3) || (val == 4)) {
      array[counter] = val;
      Serial.print("In  ");
      Serial.print(counter);                
      Serial.print(" saving ");            
      Serial.println(val);
      delay(200);
      counter++;
      if (counter == MAX) {
        counter = 0;
      } 
    }
  }

  temp = counter;
  counter = 0;

  for (i = 0; i < temp; i++) {
    if (array[i] % 2 == 0) {
      L1 = 2;
      L2 = array[i] / 3 + 3; 
    } else {
      L2 = 5;
      L1 = array[i] % 3 + 3;    
      }

    if (readButtons(5) != 5) {
     digitalWrite (L1, HIGH);
     if (readButtons(5) != 5) {
      digitalWrite (L2, HIGH);
      delay(1000);
      digitalWrite (L1, LOW);
      digitalWrite (L2, LOW);
      if (readButtons(5) == 5) {
        i = temp;
      }
     } else {
       digitalWrite (L1, LOW);
       i = temp; 
     }
    }

  }
}

Ich habe also eine Funktion, die erkennt, ob eine Taste gedrückt wurde. Zuvor habe ich bestimmt, in welchem ​​Bereich Werte für bestimmte Tasten liegen, und alle Tasten sind so an Analog-Pin 5 angeschlossen , außer ich habe sie 6 und meine Widerstände haben 2200 Ohm. Imwhile () {...}Schleife, während die 5. Taste nicht gedrückt wird, "schaut" Arduino, ob eine der ersten vier Tasten gedrückt wurde. Wenn es war, speichern Sie es in einem Array und wenn nicht, "suchen Sie weiter". Wenn die 5. Taste gedrückt wird, brechen wir aus und speichern die letzte bekannte Stelle im Array, in der der Wert gespeichert wurde, und setzen den Stellenzähler auf Null, sodass Arduino beim erneuten Starten die Werte an der ersten Stelle des Arrays speichert. Dann bestimme ich basierend auf dem, was gespeichert ist, welcher Pin/LED aufleuchten wird. Wenn zu irgendeinem Zeitpunkt während der blinkenden LEDs die 5. Taste erneut gedrückt wird, stoppt Arduino das Blinken und wartet erneut auf die Betätigung der ersten vier Tasten. So soll es theoretisch funktionieren. In der Praxis kann ich es immer noch nicht dazu bringen, jedes Mal zu blinken, wenn die 5. Taste erneut gedrückt wird. Ich muss mehrmals drücken, Manchmal sind zwei oder manchmal sogar mehr Drücken erforderlich, wenn ich möchte, dass es aufhört zu blinken. Ich glaube nicht, dass die Verwendung von Interrupts helfen wird, da ich nicht weiß, wie ich sie in meinem Problem implementieren soll. Hier ist meine Schaltung (außer ich habe Arduino Duemilanove Atmega 168). Die LEDs gehen von rechts nach links von 1 bis 4:

Schema

Antworten (3)

Aus Ihrer Beschreibung scheint es, dass Sie den Schalter entprellen müssen .

Du kannst das

Da Sie anscheinend eine Art Widerstandsleiter verwenden, um mehrere Tasten an einem ADC-Port zu lesen, wird dies etwas komplizierter.

Dieser Abschnitt Ihres Codes sieht für mich seltsam aus:

    if (readButtons(5) != 5) {
       digitalWrite (L1, HIGH);
       if (readButtons(5) != 5) {
         digitalWrite (L2, HIGH);

Ihre readButtons(5)-Funktion gibt 0 zurück, es sei denn, eine Änderung im Schaltflächenstatus ist aufgetreten.

Also für das digitalWrite (L2, HIGH); auszuführenden Code müssten Sie zwei Tastendrücke in sehr schneller Folge erkennen.

Ich denke, das muss ein Fehler sein, da ich mir keinen plausiblen Grund dafür vorstellen kann, dass der Code so ist.

Vielleicht beabsichtigen Sie, Pressen um eine Sekunde zu trennen (zum Beispiel)?

Dann sollte der Code sicherlich sein:

        if (readButtons(5) != 5) {
          digitalWrite (L1, HIGH);
          delay(1000);
          if (readButtons(5) != 5) {
            digitalWrite (L2, HIGH);

Ich denke, das Problem ist die Art und Weise, wie Sie große Verzögerungen anwenden, die das schnelle Scannen der Schaltflächen verhindern.

Im folgenden (ungetesteten) Code verwende ich kleine 1-ms-Verzögerungen, die mehrmals ausgeführt werden, während die Schaltflächen weiter gescannt werden

#define MAX 50
const int LED1 = 2;
const int LED2 = 3;
const int LED3 = 4;
const int LED4 = 5;
int array[MAX];
int old_b = 0;
int val;
int counter = 0;
int i;
int temp;
int L1;
int L2;

void setup()
{
    pinMode(A5, INPUT_PULLUP);
    Serial.begin(9600);
}

int readButtons(int pin)
{
    int b, c;
    c = analogRead(pin);
    Serial.print("analogRead =  ");
    Serial.println(c);
    //delay(100);

    if(c > 1015)
    {
        b = 0;
    }
    else
        if(c > 70 && c < 76)
        {
            b = 1;
        }
        else
            if(c > 122 && c < 128)
            {
                b = 2;
            }
            else
                if(c > 169 && c < 175)
                {
                    b = 3;
                }
                else
                    if(c > 209 && c < 217)
                    {
                        b = 4;
                    }
                    else
                        if(c > 247 && c < 256)
                        {
                            b = 5;
                        }
                        else
                            if(c > 280 && c < 291)
                            {
                                b = 6;
                            }
                            else
                            {
                                b = 0;
                            }

    if(b == old_b)
    {
        return 0;
        old_b = b;
    }
    else
    {
        return b;
        old_b = b;
    }
}

void loop()
{
    unsigned char counter_var = 0;
    val = readButtons(5);  // read the buttons

    while(val != 5)
    {
        val = readButtons(5);  // read the buttons

        if(counter_var == 0)
        {
            if((val == 1) || (val == 2) || (val == 3) || (val == 4))
            {
                counter_var == 200;  // to apply ~200ms delay
                array[counter] = val;
                Serial.print("In  ");
                Serial.print(counter);
                Serial.print(" saving ");
                Serial.println(val);
                //delay(200);
                counter++;

                if(counter == MAX)
                {
                    counter = 0;
                }
            }
        }
        else
        {
            counter_var--;  // if delay>0 then this decrements and counts delay ms
            delay(1);
        }
    }

    counter_var = 0;
    temp = counter;
    counter = 0;

    for(i = 0; i < temp; i++)
    {
        if(array[i] % 2 == 0)
        {
            L1 = 2;
            L2 = array[i] / 3 + 3;
        }
        else
        {
            L2 = 5;
            L1 = array[i] % 3 + 3;
        }

        if(readButtons(5) != 5)
        {
            digitalWrite(L1, HIGH);

            if(readButtons(5) != 5)
            {
                digitalWrite(L2, HIGH);
                delay(1000);
                digitalWrite(L1, LOW);
                digitalWrite(L2, LOW);

                if(readButtons(5) == 5)
                {
                    i = temp;
                }
            }
            else
            {
                digitalWrite(L1, LOW);
                i = temp;
            }
        }
    }
}

Die wichtigste Änderung, die ich vorgenommen habe, ist im folgenden Teil ( start of loop() )

  unsigned char counter_var = 0;
    val = readButtons(5);  // read the buttons

    while(val != 5)
    {
        val = readButtons(5);  // read the buttons

        if(counter_var == 0)
        {
            if((val == 1) || (val == 2) || (val == 3) || (val == 4))
            {
                counter_var == 200;  // to apply ~200ms delay
                array[counter] = val;
                Serial.print("In  ");
                Serial.print(counter);
                Serial.print(" saving ");
                Serial.println(val);
                //delay(200);
                counter++;

                if(counter == MAX)
                {
                    counter = 0;
                }
            }
        }
        else
        {
            counter_var--;  // if delay>0 then this decrements and counts delay ms
            delay(1);
        }
    }

und ich habe die delay(100)von entferntreadButtons()

Ich habe Ihren Code müde und leider hat er nicht funktioniert. Der ohne die Änderungen in der Schleife würde perfekt funktionieren, außer dass er irgendwie immer vergisst, den Befehl der ersten gedrückten Taste auszuführen. Wenn ich zum Beispiel 1,2,2,3,4 drücke, wird es ausgeführt, als hätte ich 2,2,3,4 gedrückt. Mit den Korrekturen in der Schleife erkennt es das Drücken der 5. Taste nicht, dh es beginnt/endet nicht zu blinken, nachdem die 5. Taste gedrückt wurde.
@Mate, also funktioniert die Abtretung für 1-4 Tasten und Sie haben nur ein Problem mit der Erkennung von Taste 5 in meinem Code?
Ja, wenn in der Schleife ist der Code aus dem zweiten Teil Ihrer Antwort.
@Mate Was Sie verwendet haben, ist der vollständige Code des ersten Teils meiner Antwort, richtig? Der zweite ist bereits ein Teil des ersten und sollte ignoriert werden.
Entschuldigung, das war mir nicht klar. Dann ist das einzige Problem, dass es sich nicht an das Drücken einer ersten Taste erinnert/speichert, die gedrückt wurde, egal welche zuerst gedrückt wurde.
@Mate Ich habe den Code in einem Simulator überprüft und scheint gut zu funktionieren (vielleicht müssen Sie nur die Verzögerung von 200 auf 500 oder mehr erhöhen, um mehrere Speicherereignisse für jeden 1-4-Tastendruck zu verhindern), also bin ich es nicht sicher, warum Sie ein Problem damit haben. Sind Sie sicher, dass der Spannungspegel für Taste 5 richtig eingestellt ist, um vom ADC erkannt zu werden?
Ich bin positiv. Ich habe meine Schaltpläne hinzugefügt. Wenn Sie möchten, können Sie es selbst ausprobieren und sehen, ob Sie ähnliche Ergebnisse erzielen.
@alexan_e - Können Sie uns sagen, welchen Simulator Sie verwendet haben?
@Ricardo proteus
@Mate Also, wenn ich richtig verstehe, funktioniert der von mir bereitgestellte Code, aber aus irgendeinem Grund erkennt/speichert er nie die erste gedrückte Taste, oder? Bekommst du im seriellen Terminal eine Meldung, dass diese erste Taste gedrückt wurde?
@alexan_e: Manchmal erkennt es den ersten Tastendruck nicht, aber es gibt immer eine Meldung im seriellen Terminal, dass es erkannt wurde.