Wie kann ich folgenden Programmtext verkürzen?

Hallo!

Ich, 15, bin blutiger Anfänger beim Thema Arduino.

Ich habe 10 LED's angeschlossen und möchte die ein paar Spielereien machen lassen, unter anderem soll das Licht sich von der Mitte gleichzeitig zu beiden Seiten weg- und wieder zurückbewegen. Um die Gleichzeitigkeit zu realisieren, kann ich meiner Meinung nicht auf eine Schleife o. ä. zurückgreifen. Jetzt ist aber sehr viel Text entstanden.

Ich würde euch den kompletten Code reinsetzen, damit ihr alles versteht.

int i;
int a;

void setup() {
  for (i=1; i<11; i++) {
    pinMode(i, OUTPUT);
  }

}

void loop() {
  hinundher();

  ausbreiten();
  ausbreiten();
  
  // delay(10000);
}


void hinundher() {
  for (a=1; a<3; a++) {
  
    for (i=1; i<11; i++) {
     digitalWrite(i, HIGH);
      delay(250);
      digitalWrite(i, LOW);
    }

    for (i=9; i>1; i--) {
      digitalWrite(i, HIGH);
      delay(250);
      digitalWrite(i, LOW);
    }
  }
}


void ausbreiten() {
  digitalWrite(5, HIGH);
  digitalWrite(6, HIGH);
  delay(200);
  digitalWrite(5, LOW);
  digitalWrite(6, LOW);

  digitalWrite(4, HIGH);
  digitalWrite(7, HIGH);
  delay(200);
  digitalWrite(4, LOW);
  digitalWrite(7, LOW);

  digitalWrite(3, HIGH);
  digitalWrite(8, HIGH);
  delay(200);
  digitalWrite(3, LOW);
  digitalWrite(8, LOW);

  digitalWrite(2, HIGH);
  digitalWrite(9, HIGH);
  delay(200);
  digitalWrite(2, LOW);
  digitalWrite(9, LOW);

  digitalWrite(1, HIGH);
  digitalWrite(10, HIGH);
  delay(200);
  digitalWrite(1, LOW);
  digitalWrite(10, LOW);

  digitalWrite(2, HIGH);
  digitalWrite(9, HIGH);
  delay(200);
  digitalWrite(2, LOW);
  digitalWrite(9, LOW);

  digitalWrite(3, HIGH);
  digitalWrite(8, HIGH);
  delay(200);
  digitalWrite(3, LOW);
  digitalWrite(8, LOW);

  digitalWrite(4, HIGH);
  digitalWrite(7, HIGH);
  delay(200);
  digitalWrite(4, LOW);
  digitalWrite(7, LOW);
}

Ich hoffe auch, dass ich mich klar genug ausgedrückt habe.
Bitte bedenkt bei eurer Antwort, ich bin ziemlicher Anfänger :).

Vielen Dank schonmal!
Adrian

Du hast vergessen den Output die jeweilige Pinnummer zu zuweisen.
(nicht getestet)

         //Aufruf durch LEDs[0,1,2,...9]
const uint8_t LEDs[10] = {2,3,4,5,6,7,8,9,10,11};
...
for (uint8_t zaehler = 0; zaehler < 10; zaehler++) //10 < reicht aus, da Array bei 0 anfaengt.
{
  pinMode(zaheler, OUTPUT);
}
...
void loop()
{
  digitalWrite(LEDs[0], HIGH);

//oder mit forschleife fuer mehrere LEDs nach einander
  for (uint8_t x = 0; x < 10; x++)
{
  digitalWrite(LEDs[x], HIGH);
}
}

Hallo,

beide LEDs jeweils direkt hintereinander geschalten ist wie gleichzeitig. Ein digitalWrite benötigt 4µs. Wenn das immer noch zu viel ist, dann musste dich mit dem direkten Zugriff auf Portregister und Binärcode befassen. Dann kannste wirkliche alle Bits eines Ports gleichzeitig schalten. Ob das notwendig ist steht auf einem anderen Blatt.

Ja, schön! Herzlich willkommen hier im Forum!

Als erste Erweiterung des Blink-Sketches schon sehr schön.

Ich geh mal davon aus, dass der Sketch das macht was er soll.
Und jetzt?

Der Sketch verwendet 1506 Bytes (4%) des Programmspeicherplatzes

was willst du da verkürzen ? Das ginge natürlich. Aber jetzt, wo du es fertig hast?

@ grillgemuese: ich sehe kein Problem, in der Schleife die 10 Pins (1 .. 10) auf OUTPUT zu setzen.


Zum Thema "gleichzeitig":

  delay(200);
  digitalWrite(2, LOW);
  digitalWrite(9, LOW);

  digitalWrite(3, HIGH);
  digitalWrite(8, HIGH);
  delay(200);

Diese 4 "Aktionen" siehst du sicher gleichzeitig. Oder ?

Generell gilt aber:
Wenn irgend etwas "gleichzeitig" gehen soll, ist das kein Problem, dann darf man nur nicht mit delay() und gar delay() in Schleifen arbeiten.

Dazu noch etwas Trickserei zum LOW setzen und das Delay drunter

Du könntest es dir einfach machen, und alle LED ausschalten, dann die im aktuellen Schritt die gewünschten LED (z.B. in einer Schleife ) anschalten, dann erst delay(), damit du auch was siehst.

void loop() {

   for (int i = 1; i < 14; i++) digitalWrite(i, LOW);
   digitalWrite(13, HIGH);
   delay(100);
}

hier flackert nichts !

Hi

noiasca:
... und das Delay drunter.

Wobei Es Da schönere Möglichkeiten gibt, auf das Ende einer Wartezeit zu reagieren.
Ok, hier soll Nichts zwischen drin gemacht werden - der Stromverbrauch ist der Gleiche und intern rennt der Arduino die ganze Wartezeit auch nur im Kreis, aber (s/w)ollten wir 'den Neuen' nicht eher den Weg weg von delay() zeigen?

Wie geschrieben, hier ist das delay() kein Problem, da eh nur gewartet wird, bis die nächste Aktion gestartet wird und das Menschlein am 'anderen Ende' halt nicht so schnell mit gucken ist, aber beim nächsten Sketch soll in der Zwischenzeit dann doch noch was sinnvolles ergänzt werden und dann ist's Essig mit delay().

MfG

Suchworte, sofern Interesse:
Endlicher Automat, Blink ohne delay, Nachtwächer Erklärung,Statemachine

Ich würde empfehlen, einen Schritt nach dem anderen.

Mein Codeschnippsel soll die explizit angefragte "Verkürzung" bringen, und ich denke das tut es (massiv).

Was dann noch durch Austausch gewisser Delays mit einer Statemachine drinnen ist, müsste man ausprobieren, machst du?

Edit:
ja schon.

Original:
Der Sketch verwendet 1506 Bytes (4%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 13 Bytes (0%) des dynamischen Speichers, 2035 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.

mit dieser Änderung

void ausbreiten(){
  // von innen nach außen
  for (byte j=0; j<5; j++) {                                  
    for (byte i = 1; i < 11; i++) digitalWrite(i, LOW);       // gemäß michael_x  
    digitalWrite(5-j, HIGH);
    digitalWrite(6+j, HIGH);
    delay(200);
  }

  // von außen nach innen
  for (byte j=4; j>0; j--) {
    for (byte i = 1; i < 11; i++) digitalWrite(i, LOW);        
    digitalWrite(5-j, HIGH);
    digitalWrite(6+j, HIGH);
    delay(200);
  }
}

nur mehr
Der Sketch verwendet 1270 Bytes (3%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 13 Bytes (0%) des dynamischen Speichers, 2035 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.

Meine Versuche dies über eine Statemachine machen, verschlankt den Code nicht wirklich. Das müsste sich wer anderer ansehen.

Hab aber jetzt einen ganz anderen Ansatz dafür:

Man definiert einfach die Abfolge als Bytemuster und lässt es laufen.

Wenn man sich die ganzen unnützen Kommentare wegdenkt, dann ist das wirklich sehr einfacher Code, nicht wirklich länger als der Ausgangssketch, aber super einfach zum erweitern.

// http://forum.arduino.cc/index.php?topic=518131.0
// Variante 3: Definition eines Musters das abgearbeitet wird:

#define DEBUG_UART 1                   // Debugausgaben auf Serieller Schnittstelle falls man keine 10 LEDs hat: 0 nein / 1 ja 

                             //       a987654321              // das Muster, einfach als Bitfolge dann kann man es einfach in der IDE "hinmalen"
const uint16_t     pattern[]={0b0000000000000001,             // ex hinundher() Durchgang 1
                              0b0000000000000010,
                              0b0000000000000100,
                              0b0000000000001000,
                              0b0000000000010000,
                              0b0000000000100000,
                              0b0000000001000000,
                              0b0000000010000000,
                              0b0000000100000000,
                              0b0000001000000000,
                              0b0000000100000000,
                              0b0000000010000000,
                              0b0000000001000000,
                              0b0000000000100000,
                              0b0000000000010000,
                              0b0000000000001000,
                              0b0000000000000100,
                              0b0000000000000010,
                              0b0000000000000001,             // 19 pattern haben wir jetzt
                              0b0000000000000001,             // ex hinundher() Durchgang 2
                              0b0000000000000010,
                              0b0000000000000100,
                              0b0000000000001000,
                              0b0000000000010000,
                              0b0000000000100000,
                              0b0000000001000000,
                              0b0000000010000000,
                              0b0000000100000000,
                              0b0000001000000000,
                              0b0000000100000000,
                              0b0000000010000000,
                              0b0000000001000000,
                              0b0000000000100000,
                              0b0000000000010000,
                              0b0000000000001000,
                              0b0000000000000100,
                              0b0000000000000010,
                              0b0000000000000001,         // 38 pattern haben wir jetzt
                              0b0000000000110000,         // ex ausbreiten()
                              0b0000000001001000,
                              0b0000000010000100,
                              0b0000000100000010,
                              0b0000001000000001,
                              0b0000000100000010,
                              0b0000000010000100,
                              0b0000000001001000,
                              0b0000000000110000,        
                              0b0000000000110000,         // ex ausbreiten() - 2
                              0b0000000001001000,       
                              0b0000000010000100,
                              0b0000000100000010,
                              0b0000001000000001,
                              0b0000000100000010,
                              0b0000000010000100,
                              0b0000000001001000,
                              0b0000000000110000};

uint16_t totalNoPattern = 0;           // soviele Pattern gehen zwar nie auf einen UNO, aber mehr als uint8_t könnten es schon werden. man könnte ein paar Byte sparen wenn man ein fixes precompiler #define oder ein const macht.
uint8_t  actualPattern = 0;            // welches Muster soll aktuell ausgegeben werden           
uint32_t lastMillis = 0;               // wann wurde das letzte mal ein Update der LEDs gemacht
const uint8_t myIntervall = 200;       // Achtung falls mehr als 255ms gewünscht umstellen auf ein uint16_t

void setup() {
  #if DEBUG_UART
  Serial.begin(115200);               
  #endif
  for (uint8_t i = 1; i<11; i++) {
    pinMode(i, OUTPUT);
  }
  totalNoPattern = sizeof(pattern) / sizeof(pattern[0]);   // Ermittlung wie viele Pattern definiert wurden, ich mach das zur Laufzeit, weil ich mir das abzählen sparen wollte.
}

void loop() {
  if (millis()-lastMillis>=myIntervall)
  {
    actualPattern++;
    if (actualPattern>=totalNoPattern) actualPattern=0;
    for (uint8_t i = 0; i<10; i++)                          // von der Vorgabe her reichen die 10 - werden alle 16 Leds benötigt müsste man auch im setup() mehr initialisieren
    {
      if (pattern[actualPattern] & (1<<i)) {
        #if DEBUG_UART
        Serial.print(F("X"));                            
        #endif
        digitalWrite(i+1, HIGH); }
      else {
        #if DEBUG_UART
        Serial.print(F(" "));
        #endif
        digitalWrite(i+1, LOW);}         
    }
    #if DEBUG_UART
    Serial.print(F(" - "));    
    Serial.println(actualPattern);
    #endif
    lastMillis=millis();
  }
  // do what ever you want unblocked here
}

Geht halt zu Lasten vom RAM:
Der Sketch verwendet 1100 Bytes (3%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 128 Bytes (6%) des dynamischen Speichers, 1920 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.

Wer keine 10 LEDs hat (oder wie ich, keine Lust hat das zusammenzustecken) kann die Test Ausgabe auf Serial aktivieren (der Konflikt von PIN1/2 und SERIAL ist natürlich nicht schön, aber es soll ja nur ein Test sein).

Fachlich gibt es einen Unterschied zum Ursprungspost: ich habe keine Unterscheidung ob 200 oder 250ms. Ansonsten sollte der Sketch genau das gleiche machen - aber frei von Delay.