20 Neopixel mit 20 Tastern steuern

Hey Leute,

für ein neues Projekt verwende ich einzelne NeoPixel. Dabei soll jeweils ein Pixel mit jeweils einem Taster verbunden sein. Beim Betätigen des Tasters, soll das Pixel dann für knapp eine Sekunde aufleuchten und dann wieder ausgehen.
Ich habe insgesamt 20 Taster und 20 Neopixel.
Mein Code sieht für ein Neopixel so aus:

#include <Adafruit_NeoPixel.h>
#define PIN               3
#define NUMPIXELS         1

const int schalter = 7;
int push;



Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);



void setup() {
  pixels.begin(); //This initializes the NeoPixel library
  pinMode(schalter, INPUT);
  Serial.begin(9600);

}

void loop() {
  
  push = digitalRead(schalter); //
  Serial.println(push);


  if (push == 1) //Verarbeitung: Wenn der taster gedrückt ist (Das Spannungssignal ist hoch)
  { //Programmabschnitt des IF-Befehls öffnen.
    pixels.setPixelColor(0, pixels.Color(0, 100, 0)); //dann soll die LED leuchten
    pixels.show(); 
    delay (900); //und zwar für für 5 Sekunden (5000 Millisekunden).
    pixels.setPixelColor(0, pixels.Color(0, 0, 0)); //danach soll die LED aus sein.
    pixels.show(); 
  } //Programmabschnitt des IF-Befehls schließen.
  else //...ansonsten...
  { //Programmabschnitt des else-Befehls öffnen.

    pixels.setPixelColor(0, pixels.Color(0, 0, 0)); //...soll die LED aus sein.
    pixels.show(); 
  } //Programmabschnitt des else-Befehls schließen.
  
}

Ich habe jetzt schon etwas herum probiert bin aber auf keine funktionierende Lösung gekommen wie ich nun die anderen Taster + NeoPixel zum laufen bekomme.
Das war mein Lösungsansatz:

#include <Adafruit_NeoPixel.h>
#define PIN               3
#define NUMPIXELS         1
#define PIN1              5

const int schalter = 7;
const int schalter1 = 8;
int push;
int push1;



Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);



void setup() {
  pixels.begin(); //This initializes the NeoPixel library
  pinMode(schalter, INPUT);
   pinMode(schalter1, INPUT);
  Serial.begin(9600);



}

void loop() {
  
  push = digitalRead(schalter); //
  Serial.println(push);


  if (push == 1) //Verarbeitung: Wenn der taster gedrückt ist (Das Spannungssignal ist hoch)
  { //Programmabschnitt des IF-Befehls öffnen.
    pixels.setPixelColor(0, pixels.Color(0, 100, 0)); //dann soll die LED leuchten
    pixels.show(); 
    delay (900); //und zwar für für 5 Sekunden (5000 Millisekunden).
    pixels.setPixelColor(0, pixels.Color(0, 0, 0)); //danach soll die LED aus sein.
    pixels.show(); 
  } //Programmabschnitt des IF-Befehls schließen.
  else //...ansonsten...
  { //Programmabschnitt des else-Befehls öffnen.

    pixels.setPixelColor(0, pixels.Color(0, 0, 0)); //...soll die LED aus sein.
    pixels.show(); 
  } //Programmabschnitt des else-Befehls schließen.



 push1 = digitalRead(schalter1); //
  Serial.println(push1);


  if (push1 == 1) //Verarbeitung: Wenn der taster gedrückt ist (Das Spannungssignal ist hoch)
  { //Programmabschnitt des IF-Befehls öffnen.
    pixels.setPixelColor(0, pixels.Color(0, 100, 0)); //dann soll die LED leuchten
    pixels.show(); 
    delay (900); //und zwar für ca. 1 Sekunde 
    pixels.setPixelColor(0, pixels.Color(0, 0, 0)); //danach soll die LED aus sein.
    pixels.show(); 
  } //Programmabschnitt des IF-Befehls schließen.
  else //...ansonsten...
  { //Programmabschnitt des else-Befehls öffnen.

    pixels.setPixelColor(0, pixels.Color(0, 0, 0)); //...soll die LED aus sein.
    pixels.show(); 
  } //Programmabschnitt des else-Befehls schließen.
  
}

Habt ihr einen Lösungsansatz?

Vielen Dank schonmal im Vorraus.

Okay vielen Dank, habe mir BlinkWithoutDelay angesehen. Nur noch einmal zum Verständnis meinerseits:
Ich habe 20 Taster und 20 Neopixel. Beim drücken eines Tasters, soll das Feedback das Leuchten einer bestimmten Farbe sein. Nachdem das NeoPixel aus ist. Drücke ich wieder einen beliebigen Taster und es leuchtet wieder eine bestimmte Farbe. Und so weiter. Durch den Delay in meinem Code, Stoppt das Programm aber läuft doch nach der 1 Sekunde wieder weiter und ich kann den nächsten Taster betätigen oder nicht?
Im Anhang seht ihr meinen Aufbau.

Und warum wäre es dann besser statt des Delay mit milli zu arbeiten?

Hi

Was passiert, wenn Du Taster 1 drückst und dann drei Sekunden Nichts machst?
LED 1 leuchtet die eine Sekunde, geht aus und der Arduino wartet auf den nächsten Tastendruck.
Genau, was Du willst.

Was aber, wenn Du Taste 1 drückst und über die Tasten 2 bis 5 'drüberwischt'?
LED 1 leuchtet die eine Sekunde, geht aus, der Arduino wartet auf den nächsten Tastendruck.
Was ist hier mit den LEDs für die Taster 2 bis 5?

Beim 'Blink_without_delay' merkst Du Dir bei jedem Tastendruck nur die aktuelle Zeit und schaltest die entsprechende LED an.
Das Ausschalten macht der Arduino, wenn die Zeit dafür reif ist!
Dieser schaut bei jedem loop-Durchlauf nach, ob die Laufzeit abgelaufen ist und schaltet dann die LED aus (und merkt sich, daß die LED aus ist - sonst würde die LED in JEDEM weiteren Durchlauf AUS geschaltet werden - Das kann aber auch schneller sein, als die zusätzliche Prüfung!!)

Du brauchst Dafür pro LED einen Merker für die aktuelle Zeit (32bit unsigned) und ggf. einen Merker, ob die LED gerade AN oder AUS ist (boolean).

Bei 20 LEDs würde ich Das in ein Array, besser in ein struct verpacken - in diversen Nachbar-Threads wird gerade Ähnliches bearbeitet.

MfG

Was aber, wenn Du Taste 1 drückst und über die Tasten 2 bis 5 'drüberwischt'?
LED 1 leuchtet die eine Sekunde, geht aus, der Arduino wartet auf den nächsten Tastendruck.
Was ist hier mit den LEDs für die Taster 2 bis 5?

Okay ich verstehe worauf du hinauswillst. In diesem Falle würden LED 2-5 nicht leuchten da das Programm für die eine Sekunde stehen geblieben ist. Richtig?!

Beim 'Blink_without_delay' merkst Du Dir bei jedem Tastendruck nur die aktuelle Zeit und schaltest die entsprechende LED an.
Das Ausschalten macht der Arduino, wenn die Zeit dafür reif ist!
Dieser schaut bei jedem loop-Durchlauf nach, ob die Laufzeit abgelaufen ist und schaltet dann die LED aus (und merkt sich, daß die LED aus ist - sonst würde die LED in JEDEM weiteren Durchlauf AUS geschaltet werden - Das kann aber auch schneller sein, als die zusätzliche Prüfung!!)

Vielen Dank für die Ausführliche Erklärung. Hat mir wirklich geholfen!

Hi

  1. Richtig erkannt!
  2. Gerne geschehen.

MfG

Du mußt 20 Taster einlesen. Am einfachsten geht es mit einer Matrix. Wenn Du jedem Taster eine Diode spendierst kannst Du auch gleichzeitige Mehrfachtastendrücke erkennen.

Dann wenn Du weißt welcher Taster gedrückt ist schaltest Du das entsprechende Neopixel ein und nach 1 Sekunde wieder aus. wenn Du anstat delay() mit millis die Zeit bestimmst, kannst Du währen eines eingeschalteten Neopixel ein anderes einschalten. Du brauchst für jedes Neopixel eine Variable die millis() zwischenspeichert

https://www-user.tu-chemnitz.de/~heha/Mikrocontroller/Tastenmatrix.htm

Grüße Uwe

Hi

Bei 16 Tastern hätte ich den MCP2317 in den Raum geworfen - da kannst Du getrost warten, bis sich der Expander beim Arduino meldet (Leitungen INTA und INTB lassen sich entsprechend einstellen) und dann die Taster auslesen.

Wobei der Arduino, je nach verwendetem Typ, sowohl über ausreichen Platz wie über ausreichend 'Beinchen' verfügt.

MfG
Moa

PS: Da der MCP23017 (16bit) auch IN und OUT sein kann, könntest Du den ganzen Kram 'nach Außen' verlagern.
2x 16bit, 1x8bit macht 40 I/Os, Lib's sind sowohl zu dem MicroChip-Typen, wie auch anderen PortExpandern verfügbar.

Edit
Die 0 in die Bezeichnung des Expander gepackt
DaBla zum Expander
(den 'die Suchmaschine meiner Wahl' auch bei 'MCP2317' findet ...

postmaster-ino Deine Antwort läßt erahnen daß Du den titel dieser Diskussion nicht gelesen hast oder nicht weißt was Neopixel sind. Neopixel sind nichts anderes als Ws2812 und brauchen ein Datenpin und werden alle in serie geschaltet.

Grüße Uwe

Hi

Oha - Neopixel sind mir wohl bekannt - spiele ich selber mit ...
Die zwanzig Taster brachten mich aber gedanklich zum Portexpander und 2x20=40 kann man prima durch 8 teilen - so kam ich auf 20 Taster und 20 LEDs :o
Das passte auch wieder - zumindest in meinem Kopf :wink:
... und schon hatte ich mich komplett verrannt ...

Danke für's 'zurecht rücken'

MfG

postmaster-ino:
.. MCP2317 ...

Ich kenne MCP23017 und MCP23S17, den meinst Du wohl, oder?

Empfehlenswert ist die Adafruit-MCP23017-Arduino-Library.

Hi

Ich gelobe Besserung ... habe die Bezeichnung iben ausgebessert und das (mit der falschen Bezeichnung trotzdem) gefundene Datenblatt verlinkt.

Da habe ich ja Mal so ziemlich Alles zusammen gefasst, was man nicht machen sollte ... kann auch nicht Jeder :confused:

MfG

Auf combies süßer Honigspur wandelnd 1), könnte man OOP zur Realisierung bemühen:

#include <Adafruit_NeoPixel.h>
#define PIN               14  // A0 beim UNO
#define NUMPIXELS         9
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

unsigned long jetzt;                     // Variable für den aktuellen Zeitpunkt

struct LED {
  LED(const byte led, const byte pin): led(led), pin(pin), aktZustand(0), altZustand(0), schritt(0), vorhin(0) {}

  void init()
  {
    pinMode(pin, INPUT_PULLUP);
    aktZustand = digitalRead(pin);
    altZustand = aktZustand;
  }

  void run()
  {
    altZustand = aktZustand;
    aktZustand = digitalRead(pin);
    switch (schritt)
    {
      case 0:
        if (altZustand && !aktZustand)
        {
          pixels.setPixelColor(led, pixels.Color(0, 100, 0)); //dann soll die LED leuchten
          pixels.show();
          vorhin = jetzt;
          schritt++;
        }
        break;
      case 1:
        if (jetzt - vorhin >= 1000) {
          pixels.setPixelColor(led, pixels.Color(0, 0, 0)); //danach soll die LED aus sein.
          pixels.show();
          schritt = 0;
        }
    }
  }

  const byte led;
  const byte pin;
  bool aktZustand;
  bool altZustand;
  byte schritt;
  unsigned long vorhin;
};

LED pins[] {
  // LED, Tasterpin
  {0, 2},
  {1, 3},
  {2, 4},
  {3, 5},
  {4, 6},
  {5, 7},
  {6, 8},
  {7, 9},
  {8, 10}
};             // verwendete Pins (PWM) für die LEDs

void setup() {
  pixels.begin(); //This initializes the NeoPixel library
  pixels.show();
  for (LED &p : pins) p.init();
}

void loop() {
  jetzt = millis();                      // aktuelen Zeitwert an die aktive LED in die Variale jetzt übergeben
  for (LED &p : pins) p.run();
}

Anm. 1: Die von mir verwendete Grundstruktur stammt von combie aus einem anderen Thema. Besonders gefällt mir die schlichte for-Schleife.

Schau dir mal die KASCADE mit MCP23017 I2C oder MCP23S17 SPI an
der Kann mit 8 Adressierbaren IC je x16 Ports Bidirektional 400kHz
du Brauchst also 3 MCP23
wobei 1 Foll ausgang 1 Voll Eingang
und einer der Port A Eingang und PortB Ausgang sinnvoll wäre

damit bist du ganz schnell am ziel
und es Gibt eine LIB

postmaster-ino was hast Du gemacht?
Noch einer der glaubt 20 Neopixel mit 20 Ausgängen von MCP23x17 ansteuern zu müssen.
Uwe

bmbbsr:
du Brauchst also 3 MCP23

Die MCP23x17 wären für die Eingänge eine Option.

Die NeoPixel (WS2812 und baugleiche) werden aber vergleichbar Schieberegistern angesteuert und benötigen nur einen Datenpin des Arduinos.

Eine Bibliothek hatte ich in #13 bereits verlinkt.

Hi

uwefed:
postmaster-ino was hast Du gemacht?
Noch einer der glaubt 20 Neopixel mit 20 Ausgängen von MCP23x17 ansteuern zu müssen.
Uwe

Vll. sollte ich doch Mal eine Religion gründen ... das Zeug hätte ich wohl :wink:

back²topic:
Hiermit beschwöre ich Dich untertänigst, daß Das nicht meine Absicht war.
... und jetzt soll ich alleine schuld sein ... * schnüff *

:wink:

MfG