Go Down

Topic: Nach Tastendruck Drehschalter auswerten  (Read 2698 times) previous topic - next topic

Deltaflyer

Teil 2 ->
Code: [Select]


// Funktion run3Points    3 Pixel (blau grün rot) laufen von links nach rechts / rechts nach links wobei blau der Kopf ist.
void run3Points() {
    static byte count = 0;   // Zähler für die Anzahl Schritte die gelaufen sind (damit nichts übers stripende hinausläuft
    static byte sPixel = 0;                       // am linken ende des Strip beginnen.
    static byte pixelPos = sPixel;                // absolute Position im Strip
  if (Init == true) {
     clearStrip();
     if (Dir < 0) sPixel = strip.numPixels() -1;  // am Rechten ende des Strip beginnen.
    Step = 1;
    Interval = 120;                               // 120 ms bis zum Nächsten Schritt (kannst Du nach Geschmack einstellen
  }
    if (count) {
        strip.setPixelColor(pixelPos - Dir,strip.Color(0,0,0)); // Das letzte Pixel löschen
        strip.show();
    }
    pixelPos += (Dir*Step);                       // Position um schrittweite weiter (vor oder zurück)
    count += Step;                                // Zähler um schrittweite erhöhen
    if (count == strip.numPixels()) {             // prüfen ob Stripende erreicht  
      pixelPos = sPixel;                          // pixelPos wieder auf Start
      count = 0;                                  // Schritt-Zaehler auf 0
    }
    strip.setPixelColor(pixelPos,strip.Color(170,0,0));             // Hinteres, rotes Pixel ausgeben
    strip.setPixelColor(pixelPos + Dir,strip.Color(0,170,0));       // mitleres grünes Pixel ausgeben
    strip.setPixelColor(pixelPos + (2*Dir),strip.Color(0,0,170));   // vorderstes blaues Pixel ausgeben
    strip.show();  
}
//


// Funktion Lichteffekt 2
void lichtEffekt2() {
  
}
//


// Funktion Lichteffekt 3
void lichtEffekt3() {
  
}
//


// Funktion Lichteffekt 4
void lichtEffekt4() {
  
}
//


// Funktion Richtung
void richtung() {
   if (Init == false) return;                   // Fuktion nur einmal nach Anwahl ausführen!
   Init = false;
   Interval = 0;                                // Kein Interval, ruhendes Licht.
   uint8_t startpixel = 0;                      // Für Taste  "Links"
   if(Dir < 0) startpixel = 21;                 // wenn Taste "Rechts" gedrückt
   for(int i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i,strip.Color(0,0,0));
    strip.show();
   }
 
  for(int i=0; i<15; i++) {
    strip.setPixelColor(startpixel+i,strip.Color(0,0,150));
    strip.show();
   }
}

 -> ende Teil 2

LG Stefan

Tommy56

"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

Deltaflyer

#32
Aug 28, 2017, 11:34 pm Last Edit: Aug 28, 2017, 11:39 pm by Deltaflyer
Sorry, hab grad gesehen, im angehängten Sketch ist im Setup nuch ein 'Serial.begin(9600);' drin, das kann natürlich Ersatzlos raus.
Ich hab den Anhang durch die korrigierte Version ersetzt.

@Tommy
Gern geschehen.

LG Stefan

agmue

Ich kann mir immer noch keine sinnvolle Lösung vorstellen, bei der es besser wäre, ein rein binäres Signal analog einlesen zu wollen.
Ich auch nicht. Es muß sich also um irgendein Mißverständnis handeln. Also nochmal das Thema durchgelesen, dann stoße ich auf diese Stelle:
Code: [Select]
  pinMode(A0,INPUT);          // Taste LINKS
  digitalWrite(A0,HIGH);      // interner pullup Widerstand
...
    if(analogRead(pin) < 500) // Analog Eingang erneut abfragen
      return 1;               // war gedrückt


Da könnte ich mir vorstellen: "Die Pins des Arduino können verschieden genutzt werden. So kann A0 als analoger oder als vierzehnter digitaler Eingang verwendet werden. Bei einem digitalen Signal (Taster) wäre daher digitalRead(A0) oder digitalRead(14) vorzuziehen."

An dieser Stelle darf ich noch auf meinen Vorschlag #14 hinweisen. Aber der Sketch von Stefan sieht auf den ersten Blick auch interessant aus, den schaue ich mir mal genauer an :)
Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

Deltaflyer

Danke agmue,
hoffe mein sketch hält auch noch nem 2. Blick stand. Ja ich weiss, die Tasterabfrage hätte man noch um einiges besser schreiben können, dann hät ich mir da auch noch ne Variable sparen können. Aber ich wollte bewusst menen Teil des Sketches auf Micha's Basis aufbauen. Drum hab ich auch die Abfrage der Taster und Entprellung mit dem 'Delay 150' so drin gelassen und lediglich die Erkennung, ob Taster das erste oder zweite mal gedrückt, und ob der taster wieder freigegeben worden ist, hinzugefügt.
Micha wollte ja: Richtungstaster 1. mal Drücken ->Drehschalter Position einlesen, und entsprechend Position einen Lichteffekt ausführen. Taster 2. mal drücken -> LichtEffekt stoppt. Beim nächsten Drücken eines Richtungs-Tsters wird dann wieder der Drehschalter ausgelesen.....   Bei drücken der STOP-Taste wird ein eigener Effekt auf dem Strip angezeigt. Ich hab das so kombiniert, dass damit alles wieder auf Anfang gestellt wird, also die Stop-Taste pausiert den gerade laufenden Lichteffekt nicht, sondern beendet ihn. Somit sollten immer definierte Verhältnisse herschen.

Aber sicher ist mein Sketch noch verbesserungs fähig, aber Micha soll ja auch noch was zu tun haben. Ausserdem sind ja noch drei Lichteffekte, für die ich lediglich ein leeres 'void' drin habe, wo sich micha drin austoben kann.

LG Stefan

agmue

Ich bekomme ein paar Warnungen:

Quote
In function 'void loop()':
85:48: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
 In function 'void clearStrip()':
115:35: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
 In function 'void run3Points()':
170:16: warning: comparison is always false due to limited range of data type [-Wtype-limits]
 In function 'void richtung()':
219:13: warning: comparison is always false due to limited range of data type [-Wtype-limits]
220:35: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
Nach links läuft ein blauer, grüner und roter Pumkt. Bei Stopp sind 6 Lichtpunkte in der Mitte rot. Bei Rechts blinkt NeoPixel 0 rot, da stimmt noch was nicht. Das könnte mit der Warnung zusammenhängen.

Außerdem habe ich den Effekt, daß das Lauflicht durch einen gedrückten Taster gebremst wird. delay(150); dürfte dafür der Grund sein.

Wenn Du nach Anregungen suchst, darfst Du gerne bei #14 spicken, dafür habe ich es geschrieben.
Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

Deltaflyer

OK, das mit den Warnungen und der Laufrichtung rechts schau ich mir nochmals an.
Wenn ein taster gedrückt wird, sollte das Lauflicht stehen bleiben, resp, der Strip gelöscht werden.
Hier dürfte das Delay das Lauflicht eigentlich gar nicht stören.

Mach mich gleich an die Arbeit.

LG Stefan.

Deltaflyer

#37
Aug 29, 2017, 06:42 pm Last Edit: Aug 30, 2017, 11:06 am by Deltaflyer
So, hab die Warnungen jetzt eliminiert. Ausserdem fatte ich noch nen Fehler in der Tasten-Steuerung drin.
Das Lauflicht hab ich auch noch etwas korrigiert.

Jetzt läuft der code.

LG Stefan

Deltaflyer

#38
Aug 29, 2017, 06:47 pm Last Edit: Aug 30, 2017, 11:02 am by Deltaflyer
Korrigiert!
Teil1 ->
Code: [Select]

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

#define PIN 6

Adafruit_NeoPixel strip = Adafruit_NeoPixel(36, PIN, NEO_GRB + NEO_KHZ800);

const int dsIPin[5] = {8,9,10,11,12}; // drehschalterInputPins
byte lichtEffekt = 0;                 // kein Lichteffekt gewählt
int Dir = 0;                         // Dir = die Bewegungsrichtung des Lauflichts. (-1 = links; 0 = stop; +1 = rechts)
byte Step = 1;                        // Schrittweite, zeigt an um wieviele pixel das Lauflicht in einem Schritt wandert               
bool Init = true;                     // Init aktiviert die initialisierung des jeweiligen Lichteffektes
bool keyRelease = true;               // ist true,wenn Taste wieder losgelassen wurde
bool llichtRun = false;               // wird benutzt um zu unterscheiden ob Richtungstaste das Erste oder Zweite mal gderueckt
unsigned int Interval = 0;                     /* Verzögerung beim Lauflicht in Millisekunden Von einem Pixel zum nächsten.
                                         (0=kein lauflicht) je kleiner der Wert, desto schneller läuft das Lauflicht. */
unsigned long IntervalStart; 
                                   
void setup() {
 IntervalStart = millis();
  strip.begin();
  strip.show();

  pinMode(3,INPUT_PULLUP);          // Taste LINKS, mit internem pullup Widerstand
  pinMode(4,INPUT_PULLUP);          // Taste STOP,  mit internem pullup Widerstand
  pinMode(5,INPUT_PULLUP);          // Taste RECHTS, mit internem pullup Widerstand
  for (int i=0; i<5; i++){
    pinMode(dsIPin[i],INPUT_PULLUP);   // Pins an denen der Drehschalter hängt auf Input und Pullup-Widerstand einschalten
  }
}

void loop() {
  if(keyRelease == true && readButton(3)) {
    if (llichtRun == false) {         // Taste das erste mal gedrückt
        lichtEffekt = readDSwitch();  // lichtEffekt erhält die Position des Drehschalters. (1-5)
        Init = true;                  // bei 'true' wird der Lichteffekt Initialisiert und gestartet.
        Dir = 1;                      // "Links"
        callLichtEffekt(lichtEffekt); // Lichteffekt ausführen
        llichtRun = true;             // merken dass lichteffekt gestartet
        keyRelease = false;           // Taste noch nicht wieder losgelassen
    }
    else if (llichtRun == true && keyRelease == true) {      // Taste das 2. mal gedrückt
      Interval = 0;                   // Interval aussschalten , Lauflicht anhalten
      Dir = 0;                        // Richtung auf 0 ( keine Laufrichtung)
      clearStrip();                   // Strip löschen
      lichtEffekt = 0;                // Kein LichtEffekt gewählt
      llichtRun = false;              // Taste für erneuten start vorbereiten
      keyRelease = false;             // Taste noch nicht wieder losgelassen
    }
  }
 
  if(readButton(4) && keyRelease == true) {   // "Stop" - Taste gedrückt
    Interval = 0;                     // Interval aussschalten , Lauflicht anhalten
    Dir = 0;                          // Richtung auf 0 ( keine Laufrichtung)
    stop();                           // 'Stopp'-Band anzeigen
    keyRelease = false;               // Taste noch nicht wieder losgelassen
    llichtRun = false;                // Richtungstasten für erneuten Start vorbereiten
    lichtEffekt = 0;                  // Kein LichtEffekt gewählt
    keyRelease = false;               // Taste noch nicht wieder losgelassen
  }
 
  if(keyRelease == true && readButton(5)) {
    if (llichtRun == false) {         // Taste das erste mal gedrückt
        lichtEffekt = readDSwitch();   // lichtEffekt erhält die Position des Drehschalters. (1-5)
        Init = true;                   // bei 'true' wird der Lichteffekt Initialisiert und gestartet.
        Dir = -1;                      // "Links"
        callLichtEffekt(lichtEffekt);  // Lichteffekt ausführen
        llichtRun = true;              // merken dass lichteffekt gestartet
        keyRelease = false;            // Taste noch nicht wieder losgelassen
    }
    else if (llichtRun == true) {      // Taste das 2. mal gedrückt
      Interval = 0;                    // Interval aussschalten , Lauflicht anhalten
      Dir = 0;                         // Richtung auf 0 ( keine Laufrichtung)
      clearStrip();                    // Strip löschen
      lichtEffekt = 0;                 // Kein LichtEffekt gewählt
      llichtRun = false;               // Taste für erneuten start vorbereiten
      keyRelease = false; 
    }
  }
  if (!keyRelease) {
      if (readButton(3)==0 && readButton(4)==0 && readButton(5)==0) keyRelease = true; /* gedrückte Taste
                                                                                         wurde losgelassen */
  }
 // else     // Wenn Du dieses 'else' aktivierst läuft das Licht erst NACH loslassen der Taste los!!
           // So läuft es etwas Langsamer los und erreicht das eingestellte Tempo nachlLoslassen der Taste!
  if (Interval && (millis() - IntervalStart >= Interval)) callLichtEffekt(lichtEffekt);     /* bei laufenden Lichtern
                                                                                              nächsten Schritt ausführen */
}
//Ende der Schleife (loop)

//
byte readDSwitch() {                       // Fragt den Drehschalter ab
  byte dsp=0;                              // hilfsvariable DrehSchalterPosition
  for(int n=0; n<5; n++) {
    if(digitalRead(dsIPin[n]) == LOW) {    // DrehSchalterInputs nacheinander abfragen, wenn LOW, Schalterposition gefunden
      dsp = n+1;                           // dsp bekommt nun den Positionswert (1-5) 
      break;                               // Schleife verlassen, weil Pos gefunden
    }
  }
  return dsp;                              //Positionswert zurückgeben
}

//
int readButton(int pin) {        // Taste einlesen
  if(digitalRead(pin) == LOW) {  // Analog Eingang abfragen
    delay(150);                  // Wartezeit zum erneut abfragen
    if(digitalRead(pin) == LOW)  // Analog Eingang erneut abfragen
      return 1;                  // war gedrückt
  }
      return 0;                  // war nicht gedrückt
}


// Strip löschen (all LED's off)
void clearStrip() {
   for(uint8_t i=0; i<strip.numPixels(); i++) {        // Schleife in der Länge des NeoPixel-Strip
    strip.setPixelColor(i,strip.Color(0,0,0));     // Pixel Ausschalten
   }
   strip.show();
}
//

// Funktion STOP
// zuerst alle Pixel aus, dann die mittleren 6 auf Rot
void stop() {
  clearStrip();                     // Habe das löschen des Strip's in eine eigene Funktion gepackt, da mehrfach benötigt.
 
  for(int i=0; i<6; i++) {
    strip.setPixelColor(15+i,strip.Color(150,0,0));
    strip.show();
   }
}

void callLichtEffekt(byte LiEf) {    // LiEf enthält die Nummer der auszuführenden Funktion
  switch(LiEf){
    case 1:
    run3Points();
    break;

    case 2:
    // Lichteffekt 2 ausführen
    lichtEffekt2();
    break;

    case 3:
    // Lichteffekt 3 ausführen
    lichtEffekt3();
    break;

    case 4:
    // Lichteffekt 4 ausführen
    lichtEffekt4();
    break;

    case 5:
    richtung();
    break;
  }
  IntervalStart = millis();
}
//

Deltaflyer

Und hier Teil 2 ->
Code: [Select]



// Funktion run3Points    3 Pixel (blau grün rot) laufen von links nach rechts / rechts nach links wobei blau der Kopf ist.
void run3Points() {
    static byte count;        // Zähler für die Anzahl Schritte die gelaufen sind (damit nichts übers stripende hinausläuft
    static uint8_t sPixel;                           // am linken ende des Strip beginnen.
    static uint8_t pixelPos;                         // absolute Position im Strip
  if (Init == true) {
     clearStrip();
     count = 0;
     sPixel = 0;
     if (Dir < 0) sPixel = strip.numPixels() -1;  // am Rechten ende des Strip beginnen.
     pixelPos = sPixel;
     Step = 1;
     Interval = 120;                               // 120 ms bis zum Nächsten Schritt (kannst Du nach Geschmack einstellen
  }
  if (count) {
      strip.setPixelColor(pixelPos - Dir   ,strip.Color(0,0,0));       // Das letzte Pixel löschen
      strip.show();
  }
  else {
      strip.setPixelColor(0,strip.Color(0,0,0));                      // am untren Ende verbleibendes Pixel löschen
      strip.setPixelColor(strip.numPixels()-1,strip.Color(0,0,0));    // am oberen Ende verbleibendes Pixel löschen
      strip.show();
   }

    strip.setPixelColor(pixelPos,strip.Color(170,0,0));             // Hinteres, rotes Pixel ausgeben
    strip.setPixelColor(pixelPos + Dir,strip.Color(0,170,0));       // mitleres grünes Pixel ausgeben
    strip.setPixelColor(pixelPos + (2*Dir),strip.Color(0,0,170));   // vorderstes blaues Pixel ausgeben
    strip.show();
        
    pixelPos += (Dir*Step);                       // Position um schrittweite weiter (vor oder zurück)
    count += Step;                                // Zähler um schrittweite erhöhen
  
    if (count == strip.numPixels()) {             // prüfen ob Stripende erreicht  
      pixelPos = sPixel;                          // pixelPos wieder auf Start
      count = 0;                                  // Schritt-Zaehler auf 0
    }
 Init = false;
}
//


// Funktion Lichteffekt 2
void lichtEffekt2() {
  
}
//


// Funktion Lichteffekt 3
void lichtEffekt3() {
  
}
//




LG Stefan

agmue

Warum nur 16 NeoPixel? Mit 36 sieht es besser aus :)

Außerdem scheint in der Logik noch ein "Loch" zu sein, da manchmal alle Lichter dunkel sind.
Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

Deltaflyer

Oh, sorry, ja naturlich, hab vergessen wieder auf 36 zurück zu stellen. Hatte zum testen nur nen 16er neopixel-Ring, keinen längeren Strip.

Loch?
Die logik ist so: Taste drücken: Drehschalter lesen, gewählten Effekt ausführen.
Taste wieder drücken : Efekt stoppen, alle Lichter aus.
Taste wieder drücken: Drehschalter lesen, gewählten effekt ausführen.

Und: ich lasse das Lauflicht am Ende aus dem Strip rauslaufen und starte erst dann wieder am Anfang mit 3 Lichtern.

Wenn zurzeit, so wie der sketch jetzt ist, der drehschalter in stellung 2, 3 oder 4 steht, gibt es gar kein Licht, da ich dazu keine Effekte geschrieben hab.

Das lauflicht hab ich nur geschrieben, um Micha zu zeigeni, wir das Lauflicht laufen lassen kan, ohne die loop, oder das ganze Programm in der wartezeit zu blokieren.

Und es ist Micha ja freigestellt, meinen Code nach belieben anzupassen, zu erweitern, zu optimieren - oder einfach in die Tonne zu kloppen.

LG Stefan

agmue

Taste wieder drücken : Efekt stoppen, alle Lichter aus.
Kein Fehler, sondern ein Feature, dann ist es gut :)

Und es ist Micha ja freigestellt, meinen Code nach belieben anzupassen, zu erweitern, zu optimieren - oder einfach in die Tonne zu kloppen.
Mal warten, ob er sich meldet.
Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

Deltaflyer

@agmue
Ich habe dies deshalb so gelös, weil Micha beim 2. Tastendtuck den Laufeffekt stoppen will, aber eben nicht nur 'laufende' sondern eben auch 'statische' Effekte drin hat. (den ersten, der mit den blauen Bändern, hatte er ja schon von Anfang an im Sketch). Ich wollte einfach eine optisch erkennbare Reaktion auf den 2. Tastendruck.

Und ein statischer Effekt ist etwas schwierig zum anhalten.
Ok, ich hätte z.B. auch einfach ein, zwei Pixel als Bestätigung einschalten können.

Aber auch da kann Micha ja in den Sektionen, die den 2. Tastendruck behandeln das 'clearStrip()' durch den Aufruf eines 'Bestätigung-Effektes' ersetzen, oder einfach rausnehmen.

 

Sk8erBoyZ

Hallo,
habe heute den Sketch getestet. Funktioniert einwandfrei.
Vielen Dank dafür an Stefan. Super Arbeit.
Werde mir noch ein paar Effekte dazubasteln.
Wenn ich die Beleuchtung installiert habe werde ich ein Bild oder Videolink hier posten.

mfg Micha

Go Up