Forum: Mikrocontroller und Digitale Elektronik LED-Cube Effekte weiter per Knopfdruck


von Tobias F. (tobias_f482)


Angehängte Dateien:

Lesenswert?

HI,
Ich habe mir ein LED-Cube (8x8x8) gebaut und das ganze mit einem Arduino 
Uno zum laufen gebracht. Da ich leider nicht sonderlich fit bin im 
Programmieren von den Controllern habe ich mich auf die suche nach einem 
Code gemacht um die Grundfunktion des Würfels zu erhalten. Da habe ich 
den, öffentlich zugänglichen, Code gefunden welcher im Anhang zu finden 
ist.


Das ganze funktioniert schon mal ganz gut. Jetzt hätte ich jedoch gerne, 
dass ich die einzelnen Effekte per Knopfdruck weiter drücken kann und 
die einzelnen Effekte sich solange wiederholen bis ich wieder auf den 
Knopf drücke.

Jedoch weiß ich nicht wie ich das ganze umsetzen kann?

In der Theorie müsste ich ja ein Input Pin festlegen und die einzelnen 
Effekte als Schleife. Dann müsste ich eine neue Variabel festlegen die 
die Knopfdrücke zählte und sagt ob die Beddingen erfüllt ist, damit der 
Effekt statt findet (also Knopf 1x gedrückt, erster Effekt, noch mal 
gerückt 2. Effekt usw.)?
Aber wie kann ich das in diesem Programm umsetzen?


Würde mich über Hilfe sehr freuen.

LG

von Frank L. (Firma: Flk Consulting UG) (flk)


Lesenswert?

Hallo Tobias,

schau mal hier https://www.arduino.cc/en/Reference/AttachInterrupt

In Deinem Loop brauchst Du dann nur noch einen Switch und gut ist es.

Allerdings sollest Du beachten, dass der aktuell laufende Effekt zuerst 
zu Ende bearbeitet wird bevor der nächste Effekt - der, den Du 
ausgewählt hast - startet. Willst Du das nicht, musst Du in jeden Effekt 
noch eine zusätzliche Abbruchbedingung integrieren. Also eine zweite 
Variable die im Interrupt gesetzt wird und den Effekt abbricht.

Gruß
Frank

von Tobias F. (tobias_f482)


Lesenswert?

Hallo Frank,

danke schon mal für die Antwort. Nun ist es aber so, dass ich Pin 
2,3,4,5,6,7,8,9 für die Kathoden Ansteuerung nutze. Aso ist die 
Anleitung oben ja nicht ausführbar oder?

So wie ich das sehe wird ja in diesem Teil die einzelnen Effekte 
aufgerufen:
1
 void loop() {
2
  int i, x, y, z;
3
4
  while (true)
5
  {
6
    effect_wormsqueeze (2, AXIS_Z, -1, 100, 1000);
7
    effect_rand_patharound(200, 500);
8
    effect_intro();
9
    sinelines(4000, 10);
10
    effect_random_sparkle();
11
    side_ripples (300, 500);
12
    mirror_ripples(600, 400);
13
    quad_ripples (600, 300);
14
    linespin(1500, 10);
15
    fireworks(10, 30, 500);
16
17
18
    effect_box_wamp(1000);
19
20
    effect_rain(100);
21
22
    effect_planboing(AXIS_Z, 700);
23
    effect_planboing(AXIS_Y, 700);
24
    effect_planboing(AXIS_X, 700);
25
26
    effect_blinky2();
27
28
    effect_random_filler(75, 1);
29
    effect_random_filler(75, 0);
30
31
    effect_boxside_randsend_parallel (AXIS_X, 0, 200, 1);
32
    effect_boxside_randsend_parallel (AXIS_X, 1, 200, 1);
33
    effect_boxside_randsend_parallel (AXIS_Y, 0, 300, 1);
34
    effect_boxside_randsend_parallel (AXIS_Y, 1, 300, 1);
35
    effect_boxside_randsend_parallel (AXIS_Z, 0, 600, 1);
36
    effect_boxside_randsend_parallel (AXIS_Z, 1, 600, 1);
37
    effect_axis_updown_randsuspend(AXIS_Z, 550, 5000, 0);
38
    effect_axis_updown_randsuspend(AXIS_Z, 550, 5000, 1);
39
    effect_axis_updown_randsuspend(AXIS_Z, 550, 5000, 0);
40
    effect_axis_updown_randsuspend(AXIS_Z, 550, 5000, 1);
41
    effect_axis_updown_randsuspend(AXIS_X, 550, 5000, 0);
42
    effect_axis_updown_randsuspend(AXIS_X, 550, 5000, 1);
43
    effect_axis_updown_randsuspend(AXIS_Y, 550, 5000, 0);
44
    effect_axis_updown_randsuspend(AXIS_Y, 550, 5000, 1);
45
    effect_text(1000);
46
  }
47
}

Die Zahlen bedeuten so wie ich es verstehe die Laufdauer?

Wie müsste ich das jetzt dort genau einbinden?

LG
Tobias

von Patrick J. (ho-bit-hun-ter)


Lesenswert?

Hi

Die Funktionen, Die Du da aufrufst, müssen ja irgendwo vorhanden sein - 
ein Blick darein könnte zum Verständnis positiv beitragen.

MfG

von Frank L. (Firma: Flk Consulting UG) (flk)


Lesenswert?

Hallo Tobias,

Welches Arduino Bosrd nutzt Du genau? Ein Schaltplan würde auch helfen.

Gruß
Frank

: Bearbeitet durch User
von Tobias F. (tobias_f482)


Lesenswert?

Patrick J. schrieb:
> Hi
>
> Die Funktionen, Die Du da aufrufst, müssen ja irgendwo vorhanden sein -
> ein Blick darein könnte zum Verständnis positiv beitragen.
>
> MfG

Hi,

der Komplette Code ist in der Text Datei im Anfangspost.

Frank L. schrieb:
> Hallo Tobias,
>
> Welches Arduino Bosrd nutzt Du genau? Ein Schaltplan würde auch helfen.
>
> Gruß

Ich Verwende den Arduino Uno. Der Schaltplan ist so aufgebaut wie alle 
andren LED Cubs auch die ich kenne. Aber hier findet man ihn noch mal 
sehr schön: 
http://ledcubeblog.blogspot.de/2013/05/erstellung-der-steuerplatinen.html


LG
Tobias

von Frank L. (Firma: Flk Consulting UG) (flk)


Lesenswert?

Hallo Tobias,

Du kannst beim UNO generell jeden PIN als Interrupt fähig betrachten.

Lies Dir bitte dazu das mal durch 
http://playground.arduino.cc/Main/PcInt

Um also einen zusätzlichen Taster verwenden zu können, stehen Dir die 
Eingänge A0-A5 zur Verfügung.
1
/* Pin to interrupt map:
2
 * A0-A5 (D14-D19) = PCINT 8-13 = PCIR1 = PC = PCIE1 = pcmsk1
3
 */

Möchtest Du A0 als Input für Deinen Taster verwenden, wäre die korrekte 
PIN Nummer die 14.

Wenn Du das lauffähig implementiert und verstanden hast, können wir den 
nächsten Schritt gehen.

Gruß
Frank

von Tobias F. (tobias_f482)


Lesenswert?

Hi Frank,

um ehrlich zu sein verstehe ich den Inhalt nicht der sich hinter dem 
Link befindet. Ich habe zwar jetzt raus das ich die Pins D14-D19 bzw. A0 
bis A5 als Interupt nutzen kann, jedoch ist mir die Umsetzung leider 
noch schleierhaft :(

LG
Tobias

von Frank L. (Firma: Flk Consulting UG) (flk)


Lesenswert?

Hallo Tobias,

kann ich nachvollziehen. Hast Du das Programm mal in einen Sketch 
geladen und ein wenig damit herum gespielt?

An sich ist es ziemlich einfach. Folgende Herangehensweise ist sinnvoll:

Wir nehmen an, A0 (14) ist der PIN Deiner Wahl und wir verwenden einen 
idealen Taster der nicht prellt.

Im ersten Schritt (Setup) schaltest Du den PIN auf Input und aktivierst 
PULLUP damit der Eingang aktiv High ist. Du kannst diesen Eingang dann 
durch den Taster auf LOW ziehen.
1
 pinMode(14, INPUT_PULLUP);

Im zweiten Schritt, registrierst Du den Interrupt für diesen PIN
1
  PCattachInterrupt(14, tick, FALLING);

Hier passiert jetzt folgendes, für den PIN 14 wird ein Interrupt 
registriert und eine Funktion (tick) zugewiesen, die bei fallender 
Flanke reagieren soll. In Deinem Fall also wenn der Taster gedrückt 
wird.

Deine Funktion tick könnte jetzt in etwa so aussehen:
1
volatile uint8_t effect = 0;
2
#define MAXEFFECTS 32
3
4
void tick(void) 
5
{
6
  effect++;
7
  if (effect > MAXEFFECTS)
8
  {
9
    effect = 0;
10
  }
11
}

Damit das funktioniert, musst Du alles an Code, der oberhalb von
1
volatile long ticktocks = 0;

eins zu eins übernehmen.

In Deiner Loop wertest Du jetzt die Variable effect über ein Switch aus.
1
switch( effect )
2
{
3
  case : 0
4
    effect_wormsqueeze (2, AXIS_Z, -1, 100, 1000);
5
    break;
6
  case : 1
7
    effect_rand_patharound(200, 500);
8
    break;
9
  case : 2
10
    effect_intro();
11
    break;
12
  case : 3
13
    sinelines(4000, 10);
14
    break;
15
}

Der beschriebene Weg mag nicht der beste sein, er wird aber 
funktionieren. Offen ist lediglich das Prellen des Tasters, hier wirst 
Du Dir eine Hard- oder Softwarelösung einfallen lassen müssen und die 
Möglichkeit über ein Flag einen Effekt abbrechen zu können sobald der 
Taster gedrückt wurde.

Gruß
Frank

von Tobias F. (tobias_f482)


Lesenswert?

Hi Frank,

super! Danke für die tolle Hilfe bis hier hin!


Also ich müsste ja dieses hier kopieren und einfügen:
1
 #include "pins_arduino.h"
2
/*
3
 * an extension to the interrupt support for arduino.
4
 * add pin change interrupts to the external interrupts, giving a way
5
 * for users to have interrupts drive off of any pin.
6
 * Refer to avr-gcc header files, arduino source and atmega datasheet.
7
 */
8
9
/*
10
 * Theory: all IO pins on Atmega168 are covered by Pin Change Interrupts.
11
 * The PCINT corresponding to the pin must be enabled and masked, and
12
 * an ISR routine provided.  Since PCINTs are per port, not per pin, the ISR
13
 * must use some logic to actually implement a per-pin interrupt service.
14
 */
15
16
/* Pin to interrupt map:
17
 * D0-D7 = PCINT 16-23 = PCIR2 = PD = PCIE2 = pcmsk2
18
 * D8-D13 = PCINT 0-5 = PCIR0 = PB = PCIE0 = pcmsk0
19
 * A0-A5 (D14-D19) = PCINT 8-13 = PCIR1 = PC = PCIE1 = pcmsk1
20
 */
21
22
volatile uint8_t *port_to_pcmask[] = {
23
  &PCMSK0,
24
  &PCMSK1,
25
  &PCMSK2
26
};
27
28
static int PCintMode[24];
29
30
typedef void (*voidFuncPtr)(void);
31
32
volatile static voidFuncPtr PCintFunc[24] = { 
33
  NULL };
34
35
volatile static uint8_t PCintLast[3];
36
37
/*
38
 * attach an interrupt to a specific pin using pin change interrupts.
39
 */
40
 void PCattachInterrupt(uint8_t pin, void (*userFunc)(void), int mode) {
41
  uint8_t bit = digitalPinToBitMask(pin);
42
  uint8_t port = digitalPinToPort(pin);
43
  uint8_t slot;
44
  volatile uint8_t *pcmask;
45
46
  // map pin to PCIR register
47
  if (port == NOT_A_PORT) {
48
    return;
49
  } 
50
  else {
51
    port -= 2;
52
    pcmask = port_to_pcmask[port];
53
  }
54
55
  if (port == 1) {
56
     slot = port * 8 + (pin - 14);
57
  }
58
  else {
59
     slot = port * 8 + (pin % 8);
60
  }
61
  PCintMode[slot] = mode;
62
  PCintFunc[slot] = userFunc;
63
  *pcmask |= bit;
64
  PCICR |= 0x01 << port;
65
}
66
67
void PCdetachInterrupt(uint8_t pin) {
68
  uint8_t bit = digitalPinToBitMask(pin);
69
  uint8_t port = digitalPinToPort(pin);
70
  volatile uint8_t *pcmask;
71
72
  if (port == NOT_A_PORT) {
73
    return;
74
  } 
75
  else {
76
    port -= 2;
77
    pcmask = port_to_pcmask[port];
78
  }
79
80
  *pcmask &= ~bit;
81
  if (*pcmask == 0) {
82
    PCICR &= ~(0x01 << port);
83
  }
84
}
85
86
87
static void PCint(uint8_t port) {
88
  uint8_t bit;
89
  uint8_t curr;
90
  uint8_t mask;
91
  uint8_t pin;
92
93
  curr = *portInputRegister(port+2);
94
  mask = curr ^ PCintLast[port];
95
  PCintLast[port] = curr;
96
  if ((mask &= *port_to_pcmask[port]) == 0) {
97
    return;
98
  }
99
  for (uint8_t i=0; i < 8; i++) {
100
    bit = 0x01 << i;
101
    if (bit & mask) {
102
      pin = port * 8 + i;
103
      if ((PCintMode[pin] == CHANGE
104
          || ((PCintMode[pin] == RISING) && (curr & bit))
105
          || ((PCintMode[pin] == FALLING) && !(curr & bit)))
106
          && (PCintFunc[pin] != NULL)) {
107
        PCintFunc[pin]();
108
      }
109
    }
110
  }
111
}
112
113
114
SIGNAL(PCINT0_vect) {
115
  PCint(0);
116
}
117
SIGNAL(PCINT1_vect) {
118
  PCint(1);
119
}
120
SIGNAL(PCINT2_vect) {
121
  PCint(2);
122
}
richtig?


Wo müsste ich das genau im Programm einfügen?
 Dann würde ich ja im Void Setup die Deklarierung des pins als Interup 
machen und die Funktion tick einfügen richtig? kann ich das einfach 
irgendwo einfügen im Void Setup?

Der Teil mit dem Case1,2,3 usw. wäre ja mein Effekt wechsel richtig?


LG
Tobias

: Bearbeitet durch User
von Frank L. (Firma: Flk Consulting UG) (flk)


Lesenswert?

Hallo Tobias,

Zu beiden ja :-)

Die ganzen Kommentare am Anfang kannst Du weglassen.

Du kannst ja den Sketch mal soweit fertig machen und ich schaue morgen 
nochmal drüber.

Gruß
Frank

von Tobias F. (tobias_f482)


Angehängte Dateien:

Lesenswert?

Hi super!


Ich habe das ganze, so wie glaube, richtig umgesetzt aber ich bekomme 
beim Überprüfen die Meldung "expected primary-expression before ':' 
token" und den Verweis auf
1
 case : 17


Das verstehe ich noch nicht?


Im Anhang ist Sketch, einmal als Datei und einmal als Textdokument. 
Alles was ich dazu gemacht habe, habe ich mit einem "NEU" Kommentar 
versehen.
 Danke schon mal fürs ansehen.

LG
Tobias

: Bearbeitet durch User
von Frank L. (Firma: Flk Consulting UG) (flk)


Lesenswert?

Hallo Tobias,

sieht soweit gut aus. Im Loop hast Du eine geschweifte Klammer 
vergessen.

An dieser Stelle der kritische Hinweis, gewöhn Dir direkt eine sauber 
Formatierung Deines Codes an. Dann findest Du solche Fehler schnell 
selber.
1
void loop() 
2
{
3
  while (true)
4
  {
5
    switch( effect )                                                                               //NEU Anfang
6
    {
7
      case : 0
8
        effect_wormsqueeze (2, AXIS_Z, -1, 100, 1000);
9
        break;
10
      case : 1
11
        effect_rand_patharound(200, 500);
12
        break;
13
      case : 2
14
        effect_intro();
15
        break;
16
      case : 3
17
        sinelines(4000, 10); 
18
        break;
19
      case : 4
20
        effect_random_sparkle();
21
        break;
22
      case : 5
23
        side_ripples (300, 500);
24
        break;
25
      case : 6
26
        mirror_ripples(600, 400);
27
        break;
28
      case : 7
29
        quad_ripples (600, 300);
30
        break;
31
      case : 8
32
        linespin(1500, 10);
33
        break;
34
      case : 9
35
        fireworks(10, 30, 500);
36
        break;
37
      case : 10      
38
        effect_box_wamp(1000);
39
        break;
40
      case : 11
41
        effect_rain(100);
42
        break;
43
      case : 12
44
        effect_planboing(AXIS_Z, 700);
45
        effect_planboing(AXIS_Y, 700);
46
        effect_planboing(AXIS_X, 700);
47
        break;
48
      case : 13
49
        effect_blinky2();
50
        break;
51
      case : 14
52
        effect_random_filler(75, 1);
53
        effect_random_filler(75, 0);
54
        break;
55
      case : 15
56
        effect_boxside_randsend_parallel (AXIS_X, 0, 200, 1);
57
        effect_boxside_randsend_parallel (AXIS_X, 1, 200, 1);
58
        effect_boxside_randsend_parallel (AXIS_Y, 0, 300, 1);
59
        effect_boxside_randsend_parallel (AXIS_Y, 1, 300, 1);
60
        effect_boxside_randsend_parallel (AXIS_Z, 0, 600, 1);
61
        effect_boxside_randsend_parallel (AXIS_Z, 1, 600, 1);
62
        break;
63
      case : 16 
64
        effect_axis_updown_randsuspend(AXIS_Z, 550, 5000, 0);
65
        effect_axis_updown_randsuspend(AXIS_Z, 550, 5000, 1);
66
        effect_axis_updown_randsuspend(AXIS_Z, 550, 5000, 0);
67
        effect_axis_updown_randsuspend(AXIS_Z, 550, 5000, 1);
68
        effect_axis_updown_randsuspend(AXIS_X, 550, 5000, 0);
69
        effect_axis_updown_randsuspend(AXIS_X, 550, 5000, 1);
70
        effect_axis_updown_randsuspend(AXIS_Y, 550, 5000, 0);
71
        effect_axis_updown_randsuspend(AXIS_Y, 550, 5000, 1);
72
        break;
73
      case : 17
74
        effect_text(1000);
75
        break;                                                                 //Neu Ende
76
    }
77
  }
78
}

Wenn Du jetzt noch einen Taster an A0 anschließt, sollte das ganze schon 
funktionieren. Denk aber bitte daran, Dein Taster ist nicht entprellt 
d.h. es kann passieren, dass die Variable effect mehrfach hochgezählt 
wird und der aktuelle Effekt muss zuerst zu Ende laufen bis der aktuell 
gewählte aktiv wird.

Im übrigen, kannst Du nach dem gleichen Muster einen zweiten Taster an 
A1 hängen und damit die Effekt vor und zurück aktivieren. Mit einem 
kleinen I2C LCD Display könntest Du sogar noch den aktuellen Effekt 
namentlich anzeigen lassen. Nur so mal als kleine Idee für ein paar 
schicke Erweiterungen.

Zum Thema Tasten entprellen per Hard- oder Software findest Du hier im 
Forum einiges. Schau mal in die Artikel.

Gruß
Frank

von Tobias F. (tobias_f482)


Lesenswert?

Hi,
super vielen dank!

Ich habe den Code jetzt kopiert, aber den Fehler bekomme ich trotzdem?
Kannst du mir da vielleicht weiterhelfen?


Laufen die Effekte den jetzt solange im kreis bis ich wieder auf den 
Knopf drücke? Doch eigentlich nicht? Oder stellt das
1
case : xy
 eine Schleife da?

LG
Tobias

: Bearbeitet durch User
von Frank L. (Firma: Flk Consulting UG) (flk)


Lesenswert?

Hallo Tobias,

wenn Du den Fehler immer noch bekommst, dann hast Du wahrscheinlich 
immer noch irgendwo eine Klammer zu wenig.

Die Funktionsweise ist, solange, Du nichts tust, wird der eingestellt 
Effekt wiederholt. Die Schleife ist das "while" das Switch ist quasi 
eine vereinfachte geschachtelte if Struktur. Solange sich der Inhalt der 
Variablen effect nicht ändert, wird immer derselbe Effekt wiederholt. 
Das break sorgt dafür, dass das Switch verlassen wird. Steht es nicht 
da, würde mit dem nächsten Effekt weitergemacht werden.

Falls Du den Fehler nicht finden solltest, stell den aktuellen Code 
nochmal rein, aber bitte sauber formatiert. Ich schaue dann morgen früh 
noch mal drüber.

Gruß
Frank

von Tobias F. (tobias_f482)


Lesenswert?

Hallo Frank,

ja ok das macht Sinn, also läuft es so lange weiter bis ich wieder die 
Taste drücke? Nur wieso muss dann erst der Effekt zu ende sein?


ICh bekomme leider immer immer noch den Fehler und habe auch keine 
klammer mehr gefunden die fehlt. Ich hoffe die Formatierung ist jetzt 
besser, ich gebe mir zumindest mühe!

Ich habe die  .ino Datei jetzt mal auf Google  Drive hoch geladen, da 
ich nicht weiß wie ich das vernünftig hochladen kann, ohne das die 
Formatierung kaputt geht.

https://drive.google.com/file/d/0B50RX0UnIj1yanFpM2JmRmN4bTQ/view?usp=sharing


Ich habe nur noch ein Problem mit dem Parllen. In der Anleitung hier im 
Forum dazu gibt es ja schon Code Beispiele. Aber kann ich diese einfach 
übernehmen und wo müsste ich die Programmteile dann einfügen? Vor
1
volatile uint8_t *port_to_pcmask[] = {
?


Aber um es mir mal einfach zu machen, würde es mit diesem Taster ohne 
alles, also kein Zusatz Code und keine zusätzliche Hardware gehen: 
https://www.conrad.de/de/drucktaster-50-v-dcac-0025-a-1-x-ausein-pbs-18b-tastend-1-st-701786.html?sc.ref=Product%20Details
LG
Tobias

: Bearbeitet durch User
von Frank L. (Firma: Flk Consulting UG) (flk)


Lesenswert?

Hallo Tobias,

sorry, war mein Fehler. Das case schreibt sich nicht "case : 0" sondern 
"case 0 :" :-(
1
    switch ( effect )                                                                              //NEU Anfang
2
    {
3
      case 0 :
4
          effect_wormsqueeze (2, AXIS_Z, -1, 100, 1000);
5
        break;
6
      case 1 :
7
          effect_rand_patharound(200, 500);
8
        break;
9
      case 2 :
10
          effect_intro();
11
        break;
12
      case 3 :
13
          sinelines(4000, 10);
14
        break;
15
      case 4 :
16
          effect_random_sparkle();
17
        break;
18
      case 5 :
19
          side_ripples (300, 500);
20
        break;
21
      case 6 :
22
          mirror_ripples(600, 400);
23
        break;
24
      case 7 :
25
          quad_ripples (600, 300);
26
        break;
27
      case 8 :
28
          linespin(1500, 10);
29
        break;
30
      case 9 :
31
          fireworks(10, 30, 500);
32
        break;
33
      case 10 :
34
          effect_box_wamp(1000);
35
        break;
36
      case 11 :
37
          effect_rain(100);
38
        break;
39
      case 12 :
40
          effect_planboing(AXIS_Z, 700);
41
        effect_planboing(AXIS_Y, 700);
42
        effect_planboing(AXIS_X, 700);
43
        break;
44
      case 13 :
45
          effect_blinky2();
46
        break;
47
      case 14 :
48
          effect_random_filler(75, 1);
49
        effect_random_filler(75, 0);
50
        break;
51
      case 15 :
52
          effect_boxside_randsend_parallel (AXIS_X, 0, 200, 1);
53
        effect_boxside_randsend_parallel (AXIS_X, 1, 200, 1);
54
        effect_boxside_randsend_parallel (AXIS_Y, 0, 300, 1);
55
        effect_boxside_randsend_parallel (AXIS_Y, 1, 300, 1);
56
        effect_boxside_randsend_parallel (AXIS_Z, 0, 600, 1);
57
        effect_boxside_randsend_parallel (AXIS_Z, 1, 600, 1);
58
        break;
59
      case 16 :
60
          effect_axis_updown_randsuspend(AXIS_Z, 550, 5000, 0);
61
        effect_axis_updown_randsuspend(AXIS_Z, 550, 5000, 1);
62
        effect_axis_updown_randsuspend(AXIS_Z, 550, 5000, 0);
63
        effect_axis_updown_randsuspend(AXIS_Z, 550, 5000, 1);
64
        effect_axis_updown_randsuspend(AXIS_X, 550, 5000, 0);
65
        effect_axis_updown_randsuspend(AXIS_X, 550, 5000, 1);
66
        effect_axis_updown_randsuspend(AXIS_Y, 550, 5000, 0);
67
        effect_axis_updown_randsuspend(AXIS_Y, 550, 5000, 1);
68
        break;
69
      case 17 :
70
          effect_text(1000);
71
        break;                                                                 //Neu Ende
72
    }

Gruß
Frank

von Frank L. (Firma: Flk Consulting UG) (flk)


Lesenswert?

Hallo Tobias,

jetzt zu Deinen anderen Fragen:

1. Den Taster kannst Du nehmen.

2. Der Programmablauf
Stell Dir den Code innerhalb eines case bis zum nächsten break als 
zusammen hängender Block vor. Dieser Block läuft ab egal was passiert.

Dein Taster-Interrupt würde den Block kurz unterbrechen und wenn er mit 
seiner Aktion fertig ist an die Stelle zurückkehren, von der er gekommen 
ist und den Rest des Blocks weiter abarbeiten.

Erst wenn der Block abgearbeitet ist, wird das Switch beendet und mit 
dem neuen Wert von effect wieder betreten. Wurde effect nicht verändert, 
würde der gleiche Effekt erneut laufen.

Gruß
Frank

von Tobias F. (tobias_f482)


Lesenswert?

Hi,
Ja super!

Aber ich muss nicht genau das ende des Blockes treffen wenn ich weiter 
drücken will oder? Also ich drücke, für die Zeit stoppt der Effekt, 
läuft dann wieder weiter und wechselt wenn er fertig ist in den nächsten 
Effekt richtig?

Lg
Tobias

von Frank L. (Firma: Flk Consulting UG) (flk)


Lesenswert?

Hallo Tobias,

genau richtig :-)

Gruß
Frank

von Tobias F. (tobias_f482)


Lesenswert?

Hi Frank,

ja super, dass war echt der Fehler. jetzt läuft es.

Aber mir würde noch eine Kleinigkeit zum glück fehlen: Ist es denn noch 
machbar, dass beim Tastendruck direkt der nächste Effekt starrtet und 
davor, also praktisch beim Tasten drücken, der Cube einmal komplett blau 
ist?

Das war mal so eine Idee, aber leider klappt die natürlich nicht wenn 
ich die in Void loop() packe...
1
if (digitalRead(14) == LOW) {
2
    {0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F}
3
        currentEffect++;
4
    if (currentEffect == TOTAL_EFFECTS) {
5
      currentEffect = 0;

LG
Tobias

: Bearbeitet durch User
von Frank L. (Firma: Flk Consulting UG) (flk)


Lesenswert?

Hallo Tobias,

klar geht das, aber ohne das Du Dir Programmierkenntnisse aneignest und 
das Programm verstehst, hast Du wenig bis keine Chance.

Als Tipp:

1. Variable für den Abbruch deklarieren
1
volatile uint8_t restart = 0;

in der Funktion:
1
void tick(void) 
2
{
3
  effect++;
4
  if (effect > MAXEFFECTS)
5
  {
6
    effect = 0;
7
  }
8
  restart = 1;
9
}

dann eine zusätzliche Funktion:
1
void void effect_blue()
2
{
3
// Hier muss Dein Code dafür rein
4
}

und dann überall wo er abbrechen soll.
1
if (restart == 1)
2
{
3
  effect_blue();
4
  restart = 0;
5
  return;
6
}

So in etwa könnte es aussehen.

Viel Spaß :-) Bei Fragen melden.

Gruß
Frank

von Tobias F. (tobias_f482)


Lesenswert?

Hi Frank,
Danke schon mal ich werde das nachher direkt mal ausprobieren.

Die if Schleife für den Abbruch kommt dann praktisch zusätzliche zu den 
Effekt aufrufen in den Switch? wenn ja, wo muss der den da hin? Vor ider 
hinter den Effekt?

Lg
Tobias

von Frank L. (Firma: Flk Consulting UG) (flk)


Lesenswert?

Hi Tobias,

der if Ausdruck muss in jeden Effekt immer an die Stelle wo ein Abbruch 
stattfinden soll.

z.B.
1
void effect_rain (int iterations)
2
{
3
  int i, ii;
4
  int rnd_x;
5
  int rnd_y;
6
  int rnd_num;
7
8
  for (ii = 0; ii < iterations; ii++)
9
  {
10
    rnd_num = rand() % 4;
11
12
    for (i = 0; i < rnd_num; i++)
13
    {
14
      if (restart == 1)
15
      {
16
        effect_blue();
17
        restart = 0;
18
        return;
19
      }
20
      rnd_x = rand() % 8;
21
      rnd_y = rand() % 8;
22
      setvoxel(rnd_x, rnd_y, 7);
23
    }
24
25
    delay_ms(1000);
26
    shift(AXIS_Z, -1);
27
  }
28
}

Das Beispiel ohne Gewähr :-(

Gruß
Frank

von Tobias F. (tobias_f482)


Lesenswert?

HI Frank,

ich habe jetzt in der Zeit wo ich kein Internet hatte mal etwas anderes 
probiert. Das macht auch soweit keine Fehlermeldungen. Aber im Case 9 
sagt er mir: was not declared in this scope


Ich habe die Datei noch mal auf Google hoch geladen, magst du vielleicht 
noch mal gucken?


Ich habe mich da aus einem anderem Programm für ein LED Cube bedient wo 
es so funktioniert wie ich es gerne hätte.

Hier die Datei: 
https://drive.google.com/file/d/0B50RX0UnIj1ybHZkeHdRNEtHTk0/view?usp=sharing


LG
Tobias

von Frank L. (Firma: Flk Consulting UG) (flk)


Angehängte Dateien:

Lesenswert?

Hallo Tobias,

ich habe Dir den Code korrigiert, wie immer geschweifte Klammer nicht 
mit kopiert :-(.

Aber der Code ist absolut sinn frei, da er nur durch Zufall 
funktionieren wird. Wenn Du den Taster nicht genau zum richtigen 
Zeitpunkt betätigst oder solange drückst bis der aktuelle Effekt 
abgelaufen ist, wird kein neuer Effekt durchlaufen.

Mir ist nicht klar, was Du mit dem neuen Code erreichen wolltest.

Durch die Interruptsteuerung kannst Du den Taster zu jedem Zeitpunkt 
betätigen und nach Ablauf des Effekts wird der eingestellte aufgerufen.

Gruß
Frank

von Tobias F. (tobias_f482)


Lesenswert?

Mhm, ich habe eigentlich extra die Klammern gezählt und extrem drauf 
geachtet das sie alle da sind :(

Ich habe diese Befehle hier raus genommen (link zum Code in der 
Beschreibung) https://www.youtube.com/watch?v=T5Aq7cRc-mU&t=40s

ich hatte die Idee das ganze zu kombinieren, aber das geht ja dann wohl 
doch nicht :/

Danke dir trotzdem bis hier für deine Hilfe!

LG
Tobias

: Bearbeitet durch User
von Patrick J. (ho-bit-hun-ter)


Lesenswert?

Hi

Tobias F. schrieb:
> das geht ja dann wohl doch nicht :/

Es geht so ziemlich Alles, was Du Dir vorstellen kannst!
Dein Problem besteht momentan eher darin, daß Du Dir den eigentlichen 
Ablauf nicht vorstellen kannst, wodurch es Dir nicht möglich ist, IMMER 
auf ein externes Signal entsprechend zu reagieren.
Ansätze wurden Dir ja oben schon genannt.
Da, Wo Du unterbrechen können möchtest, musst Du halt überprüfen, ob 
JETZT GERADE unterbrochen werden soll - wenn nicht, dann ganz normal 
weiter, wenn doch -> 'Alle Maschinen STOP und zurück zum Anfang'.
Du kannst die einzelnen Effekte als 'Status' durchlaufen lassen.
Bei Knopfdruck 'jetzt den nächsten Effekt' änderst Du den Status auf den 
nächsten Effekt - Mehr ist Das nicht.
Wenn der Effekt aus mehreren Status (die Mehrzahl soll ebenfalls Status 
heißen, nur das U wird wohl lang gesprochen)  besteht, wird eben so 
lange '+1' gesprungen, bis der Effekt fertig ist und dort dann an den 
Anfang des gerade abgespielten Effekt, oder zum Nächsten - ist Deine 
Wahl.

Hier ist 'Programmieren' und 'logisch Denken' gefragt, Beides kann man 
Sich aneignen und Niemand hat Das zuvor mit 'dem goldenem Löffel' 
serviert bekommen.
Das ist der größte Vorteil beim Programmieren: Es ist ALLES logisch 
(macht ein Scheitern aber nicht angenehmer ;) )

MfG

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.