Go Down

### Topic: IRremote for my 8x8x8 led cube on the mega (Read 2287 times)previous topic - next topic

#### sterretje #15
##### Mar 27, 2018, 04:17 pm
Please post your original version of the effect_rain function. I will compare it with what I presented in reply #11.
If you understand an example, use it.
If you don't understand an example, don't use it.

Electronics engineer by trade, software engineer by profession. Trying to get back into electronics after 15 years absence.

#### Roonie #16
##### Mar 28, 2018, 05:00 pm
Okè thankx,

here is the code so far .....

Ronald

#### sterretje #17
##### Mar 28, 2018, 07:25 pm
I think you're going about it the wrong way. Start with the simple loop() example that I presented and only the effect rain that I presented; both in reply #11. Does that compile? No, see comment below. Does it show the effect?

OK, for some reason I was a bit sloppy in the code that I presented in reply #11. The variable currentTime fell out and it was never initialised; effect_rain also needed a parameter in loop().

Below the modified version. Please strip everything out of loop() and keep it simple.

Code: [Select]
`unsigned long currentTime;void loop(){  // get the current time  currentTime = millis();  if (irrecv.decode(&IRresults))  {    Serial.println(IRresults.value, DEC); // Print the Serial 'results.value'    irrecv.resume();   // Receive the next value  }  effect_rain(150)}/*  effect 4 rain  In:    number of iterations  Returns:    true if all iterations completed, else false*/bool effect_rain (int iterations){  // count the number of iterations; used to be ii  static int count;  // last time that the cube was updated  static unsigned long lastUpdateTime;  PORTC = B11001100; // 4  int i;  int rnd_x;  int rnd_y;  int rnd_num;  // if number of iterations completed  if (count >= iterations)  {    // done, reset count    count = 0;    // and indicate to called that we're finished    return true;  }  if (count == 0)  {    lastUpdateTime = currentTime;    rnd_num = rand() % 4;    for (i = 0; i < rnd_num; i++)    {      rnd_x = rand() % 8;      rnd_y = rand() % 8;      setvoxel(rnd_x, rnd_y, 7);    }  }  if (currentTime - lastUpdateTime >= 1000)  {    count++;    lastUpdateTime = currentTime;    shift(AXIS_Z, -1);  }  return false;}`
Does this work? If it does, do you understand how it works? If not, ask! If it does not work, we need to look into that first.

Once it works, we can add a start and stop of the rain effect using the remote. After that we can look at adding a more complicated effect.

I understand that you're eager to see it all working but "haastige spoed is zelden goed" PS
Once you start having numbered variables, you should start using arrays.
If you understand an example, use it.
If you don't understand an example, don't use it.

Electronics engineer by trade, software engineer by profession. Trying to get back into electronics after 15 years absence.

#### Roonie #18
##### Mar 29, 2018, 05:27 pm
Hi,

Removed everything from the loop and only pasted in your code. But it wont compile
error message ;
Code: [Select]
`Arduino: 1.8.5 (Windows 7), Board:"Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)"C:\Users\Roonie\Documents\Arduino\Roon_cube_Mega\Roon_cube_Mega.ino: In function 'bool effect_rain(int)':Roon_cube_Mega:219: error: 'setvoxel' was not declared in this scope       setvoxel(rnd_x, rnd_y, 7);                               ^Roon_cube_Mega:228: error: 'shift' was not declared in this scope     shift(AXIS_Z, -1);                     ^exit status 1'setvoxel' was not declared in this scopeDit rapport zou meer informatie bevatten met"Uitgebreide uitvoer weergeven tijden compilatie"optie aan in Bestand -> Voorkeuren.`

thankx

#### sterretje #19
##### Mar 29, 2018, 06:45 pmLast Edit: Mar 29, 2018, 06:47 pm by sterretje
You removed a little bit to much At least we have something clean to start with From the code in reply #16
Code: [Select]
`// Shift the entire contents of the cube along an axis// This is great for effects where you want to draw something// on one side of the cube and have it flow towards the other// side. Like rain flowing down the Z axiz.void shift (char axis, int direction){  int i, x ,y;  int ii, iii;  int state;  for (i = 0; i < 8; i++)  {    if (direction == -1)    {      ii = i;    } else    {      ii = (7-i);    }         for (x = 0; x < 8; x++)    {      for (y = 0; y < 8; y++)      {        if (direction == -1)        {          iii = ii+1;        } else        {          iii = ii-1;        }                if (axis == AXIS_Z)        {          state = getvoxel(x,y,iii);          altervoxel(x,y,ii,state);        }                if (axis == AXIS_Y)        {          state = getvoxel(x,iii,y);          altervoxel(x,ii,y,state);        }                if (axis == AXIS_X)        {          state = getvoxel(iii,y,x);          altervoxel(ii,y,x,state);        }      }    }  }    if (direction == -1)  {    i = 7;  } else  {    i = 0;  }     for (x = 0; x < 8; x++)  {    for (y = 0; y < 8; y++)    {      if (axis == AXIS_Z)        clrvoxel(x,y,i);              if (axis == AXIS_Y)        clrvoxel(x,i,y);            if (axis == AXIS_X)        clrvoxel(i,y,x);    }  }}`
If you understand an example, use it.
If you don't understand an example, don't use it.

Electronics engineer by trade, software engineer by profession. Trying to get back into electronics after 15 years absence.

#### Roonie #20
##### Mar 29, 2018, 09:05 pmLast Edit: Mar 29, 2018, 10:48 pm by Roonie
Oh damn ..... Now I see that some `void` effects need other pieces of code to run ...

But now I put that piece of code back in the loop I get some other errors.

So I copied some more code ... in fact from the part where is says `draw functions` all the way down.

Because altervoxel , getvoxel and some others also needed some extra code.

And now it does compile but only the top layer of the cube goes on and stays on .... I think the code is not `looping` but why I do not know....

#### sterretje #21
##### Mar 30, 2018, 04:04 am
OK, that's a bug (probably) caused by if (count == 0). There is a bit of a chicken and egg problem where count is never updated because lastUpdateTime is always updated.

Looking into it.
If you understand an example, use it.
If you don't understand an example, don't use it.

Electronics engineer by trade, software engineer by profession. Trying to get back into electronics after 15 years absence.

#### sterretje #22
##### Mar 30, 2018, 05:32 amLast Edit: Mar 30, 2018, 05:33 am by sterretje
I started with the below and tested on an Uno using serial monitor. It uses your original version of effect_rain except it does not call setvoxel and shift but prints to serial monitor; some additional debug was added. It also uses delay instead of delay_ms; reason is that delay_ms did not delay 1 second.
The for (;;); is used to only run once (I could have moved it to setup from that perspective).
Code: [Select]
`void setup(){  Serial.begin(57600);}void loop(){  effect_rain(15);  for (;;);}void effect_rain (int iterations) {  PORTC = B11001100; // 4  int i, ii;  int rnd_x;  int rnd_y;  int rnd_num;  for (ii = 0; ii < iterations; ii++)  {    Serial.println();    Serial.print("currentTime = "); Serial.println(millis());    Serial.print("iteration =   "); Serial.println(ii);    rnd_num = rand() % 4;    Serial.print("rnd_num = "); Serial.println(rnd_num);    for (i = 0; i < rnd_num; i++)    {      rnd_x = rand() % 8;      rnd_y = rand() % 8;      Serial.print("rnd_x = "); Serial.println(rnd_x);      Serial.print("rnd_y = "); Serial.println(rnd_y);      Serial.println("setvoxel(rnd_x, rnd_y, 7)");    }    delay(1000);    Serial.println("shift(AXIS_Z, -1");  }}`
The output
Code: [Select]
`currentTime = 0iteration =   0rnd_num = 3rnd_x = 1rnd_y = 1setvoxel(rnd_x, rnd_y, 7)rnd_x = 2rnd_y = 2setvoxel(rnd_x, rnd_y, 7)rnd_x = 0rnd_y = 0setvoxel(rnd_x, rnd_y, 7)shift(AXIS_Z, -1          <<<<<<< little bug in the code here, missing ')'currentTime = 1021iteration =   1rnd_num = 2rnd_x = 3rnd_y = 5setvoxel(rnd_x, rnd_y, 7)rnd_x = 0rnd_y = 5setvoxel(rnd_x, rnd_y, 7)shift(AXIS_Z, -1currentTime = 2039iteration =   2rnd_num = 0shift(AXIS_Z, -1currentTime = 3040iteration =   3rnd_num = 2rnd_x = 3rnd_y = 7setvoxel(rnd_x, rnd_y, 7)rnd_x = 7rnd_y = 1setvoxel(rnd_x, rnd_y, 7)shift(AXIS_Z, -1currentTime = 4058iteration =   4rnd_num = 0shift(AXIS_Z, -1currentTime = 5058iteration =   5rnd_num = 0shift(AXIS_Z, -1currentTime = 6060iteration =   6rnd_num = 3rnd_x = 1rnd_y = 5setvoxel(rnd_x, rnd_y, 7)rnd_x = 5rnd_y = 0setvoxel(rnd_x, rnd_y, 7)rnd_x = 5rnd_y = 3setvoxel(rnd_x, rnd_y, 7)shift(AXIS_Z, -1currentTime = 7086iteration =   7rnd_num = 2rnd_x = 0rnd_y = 7setvoxel(rnd_x, rnd_y, 7)rnd_x = 1rnd_y = 2setvoxel(rnd_x, rnd_y, 7)shift(AXIS_Z, -1currentTime = 8102iteration =   8rnd_num = 0shift(AXIS_Z, -1currentTime = 9104iteration =   9rnd_num = 3rnd_x = 2rnd_y = 1setvoxel(rnd_x, rnd_y, 7)rnd_x = 3rnd_y = 5setvoxel(rnd_x, rnd_y, 7)rnd_x = 3rnd_y = 5setvoxel(rnd_x, rnd_y, 7)shift(AXIS_Z, -1currentTime = 10130iteration =   10rnd_num = 3rnd_x = 0rnd_y = 1setvoxel(rnd_x, rnd_y, 7)rnd_x = 0rnd_y = 5setvoxel(rnd_x, rnd_y, 7)rnd_x = 1rnd_y = 4setvoxel(rnd_x, rnd_y, 7)shift(AXIS_Z, -1currentTime = 11156iteration =   11rnd_num = 3rnd_x = 2rnd_y = 5setvoxel(rnd_x, rnd_y, 7)rnd_x = 1rnd_y = 1setvoxel(rnd_x, rnd_y, 7)rnd_x = 4rnd_y = 0setvoxel(rnd_x, rnd_y, 7)shift(AXIS_Z, -1currentTime = 12182iteration =   12rnd_num = 0shift(AXIS_Z, -1currentTime = 13184iteration =   13rnd_num = 2rnd_x = 4rnd_y = 4setvoxel(rnd_x, rnd_y, 7)rnd_x = 2rnd_y = 7setvoxel(rnd_x, rnd_y, 7)shift(AXIS_Z, -1currentTime = 14201iteration =   14rnd_num = 2rnd_x = 2rnd_y = 5setvoxel(rnd_x, rnd_y, 7)rnd_x = 0rnd_y = 1setvoxel(rnd_x, rnd_y, 7)shift(AXIS_Z, -1`

When using delay_ms instead of delay, the last iteration started at 922 ms.
Code: [Select]
`currentTime = 922   <<<<<<< about one seconditeration =   14rnd_num = 2rnd_x = 2rnd_y = 5setvoxel(rnd_x, rnd_y, 7)rnd_x = 0rnd_y = 1setvoxel(rnd_x, rnd_y, 7)shift(AXIS_Z, -1`

Next I fixed my version of effect_rain. To be able to compare, again serial prints were used.
Code: [Select]
`void setup(){  Serial.begin(57600);}unsigned long currentTime;void loop(){  currentTime = millis();  if (effect_rain(15) == true)  {    for (;;);  }}/*  effect 4 rain  In:    number of iterations  Returns:    true if all iterations completed, else false*/bool effect_rain (int iterations){  // count the number of iterations; used to be ii  static int count;  // last time that the cube was updated  static unsigned long lastUpdateTime;  PORTC = B11001100; // 4  int i;  int rnd_x;  int rnd_y;  // this now needs to be static so it's remembered between successive calls to effect_rain  static int rnd_num;  // if number of iterations completed  if (count >= iterations)  {    // done, reset count    count = 0;    // and indicate to called that we're finished    return true;  }  // if 'first' call or 1 second lapsed  if (count == 0 || (currentTime - lastUpdateTime >= 1000))  {    Serial.println();    Serial.print("currentTime = "); Serial.println(currentTime);    Serial.print("iteration =   "); Serial.println(count);    rnd_num = rand() % 4;    Serial.print("rnd_num = "); Serial.println(rnd_num);    for (i = 0; i < rnd_num; i++)    {      rnd_x = rand() % 8;      rnd_y = rand() % 8;      Serial.print("rnd_x = "); Serial.println(rnd_x);      Serial.print("rnd_y = "); Serial.println(rnd_y);      Serial.println("setvoxel(rnd_x, rnd_y, 7)");    }    count++;    lastUpdateTime = currentTime;    Serial.println("shift(AXIS_Z, -1)");  }  // indicate that effect_rain is still in progress  return false;}`
And the output
Code: [Select]
`currentTime = 0iteration =   0rnd_num = 3rnd_x = 1rnd_y = 1setvoxel(rnd_x, rnd_y, 7)rnd_x = 2rnd_y = 2setvoxel(rnd_x, rnd_y, 7)rnd_x = 0rnd_y = 0setvoxel(rnd_x, rnd_y, 7)shift(AXIS_Z, -1)currentTime = 1000iteration =   1rnd_num = 2rnd_x = 3rnd_y = 5setvoxel(rnd_x, rnd_y, 7)rnd_x = 0rnd_y = 5setvoxel(rnd_x, rnd_y, 7)shift(AXIS_Z, -1)currentTime = 2000iteration =   2rnd_num = 0shift(AXIS_Z, -1)currentTime = 3000iteration =   3rnd_num = 2rnd_x = 3rnd_y = 7setvoxel(rnd_x, rnd_y, 7)rnd_x = 7rnd_y = 1setvoxel(rnd_x, rnd_y, 7)shift(AXIS_Z, -1)currentTime = 4000iteration =   4rnd_num = 0shift(AXIS_Z, -1)currentTime = 5000iteration =   5rnd_num = 0shift(AXIS_Z, -1)currentTime = 6000iteration =   6rnd_num = 3rnd_x = 1rnd_y = 5setvoxel(rnd_x, rnd_y, 7)rnd_x = 5rnd_y = 0setvoxel(rnd_x, rnd_y, 7)rnd_x = 5rnd_y = 3setvoxel(rnd_x, rnd_y, 7)shift(AXIS_Z, -1)currentTime = 7000iteration =   7rnd_num = 2rnd_x = 0rnd_y = 7setvoxel(rnd_x, rnd_y, 7)rnd_x = 1rnd_y = 2setvoxel(rnd_x, rnd_y, 7)shift(AXIS_Z, -1)currentTime = 8000iteration =   8rnd_num = 0shift(AXIS_Z, -1)currentTime = 9000iteration =   9rnd_num = 3rnd_x = 2rnd_y = 1setvoxel(rnd_x, rnd_y, 7)rnd_x = 3rnd_y = 5setvoxel(rnd_x, rnd_y, 7)rnd_x = 3rnd_y = 5setvoxel(rnd_x, rnd_y, 7)shift(AXIS_Z, -1)currentTime = 10000iteration =   10rnd_num = 3rnd_x = 0rnd_y = 1setvoxel(rnd_x, rnd_y, 7)rnd_x = 0rnd_y = 5setvoxel(rnd_x, rnd_y, 7)rnd_x = 1rnd_y = 4setvoxel(rnd_x, rnd_y, 7)shift(AXIS_Z, -1)currentTime = 11000iteration =   11rnd_num = 3rnd_x = 2rnd_y = 5setvoxel(rnd_x, rnd_y, 7)rnd_x = 1rnd_y = 1setvoxel(rnd_x, rnd_y, 7)rnd_x = 4rnd_y = 0setvoxel(rnd_x, rnd_y, 7)shift(AXIS_Z, -1)currentTime = 12000iteration =   12rnd_num = 0shift(AXIS_Z, -1)currentTime = 13000iteration =   13rnd_num = 2rnd_x = 4rnd_y = 4setvoxel(rnd_x, rnd_y, 7)rnd_x = 2rnd_y = 7setvoxel(rnd_x, rnd_y, 7)shift(AXIS_Z, -1)currentTime = 14000iteration =   14rnd_num = 2rnd_x = 2rnd_y = 5setvoxel(rnd_x, rnd_y, 7)rnd_x = 0rnd_y = 1setvoxel(rnd_x, rnd_y, 7)shift(AXIS_Z, -1)`
With exception of the currentTime values (and the little bug with ')', my modified effect_rain gives the same output results so I'm comfortable that the next post will work for you.

Note the use of the return value of effect_rain in loop. effect_rain returns true if the number of iterations has been completed, else it returns false. In the example, it's used to only run a full number of iterations once.
If you understand an example, use it.
If you don't understand an example, don't use it.

Electronics engineer by trade, software engineer by profession. Trying to get back into electronics after 15 years absence.

#### sterretje #23
##### Mar 30, 2018, 05:53 am
effect_rain for your project; it's identical to the above but the serial prints are removed and setvoxel and shift are used.
Code: [Select]
`/*  effect 4 rain  In:    number of iterations  Returns:    true if all iterations completed, else false*/bool effect_rain (int iterations){  // count the number of iterations; used to be ii  static int count;  // last time that the cube was updated  static unsigned long lastUpdateTime;  PORTC = B11001100; // 4  int i;  int rnd_x;  int rnd_y;  // this now needs to be static so it's remembered between successive calls to effect_rain  static int rnd_num;  // if number of iterations completed  if (count >= iterations)  {    // done, reset count    count = 0;    // and indicate to called that we're finished    return true;  }  // if 'first' call or 1 second lapsed  if (count == 0 || (currentTime - lastUpdateTime >= 1000))  {    rnd_num = rand() % 4;    for (i = 0; i < rnd_num; i++)    {      rnd_x = rand() % 8;      rnd_y = rand() % 8;      setvoxel(rnd_x, rnd_y, 7);    }    count++;    lastUpdateTime = currentTime;    shift(AXIS_Z, -1);  }  // indicate that effect_rain is still in progress  return false;}`
Implement this in the code that you showed in reply #20 and it should work.

Now remember the comment about delay_ms in the previous post. The above code will 'rain' a lot slower; you can adjust the 1000 in the below to e.g. 100 to speed it up.
Code: [Select]
`  // if 'first' call or 1 second lapsed  if (count == 0 || (currentTime - lastUpdateTime >= 1000))`
If you understand an example, use it.
If you don't understand an example, don't use it.

Electronics engineer by trade, software engineer by profession. Trying to get back into electronics after 15 years absence.

#### Roonie #24
##### Mar 30, 2018, 11:01 pm
Wow .. super thankx,

That`s a lot to learn... Got the effect to work !! Now I need to understand how it works and how I can get it in the `big`sketch ...
I tried copy and paste ... but no joy.
And I know `hastig spoed is zelden goed... but hey, `wie niet waagt wie niet wint` .....

But I`m defenitly going to studie this, cause a `lag` in my remote isn`t what I want.

happy easter

#### sterretje #25
##### Mar 31, 2018, 06:52 am
If you don't understand, ask. I will try to explain.

As first step for going further, you can try to stop and start the effect_rain when pressing buttons on the remote. (e.g. 1-> start and 2 -> stop). That should give you an understanding.

You will need to modify all your effects; take one at a time.

I think I mentioned state machine for the more complicated effects. When you get there, shout.

If you understand an example, use it.
If you don't understand an example, don't use it.

Electronics engineer by trade, software engineer by profession. Trying to get back into electronics after 15 years absence.

#### sterretje #26
##### Mar 31, 2018, 06:47 pm
Maybe the Roon effect is a good starting point to explain and show a state machine. A state machine breaks down your code in little steps and each time you call Roon it will go to the next steps (if conditions are satisfied, e.g. a delay has lapsed or a letter is displayed).

Your comments in Roon already give you a guidance (//R, //o, //o and //n); there are a few more. You start with a fill(), next you do letters, next you move stuff and lastly you do a fill again. In between you have all kinds of delays.
Code: [Select]
`fillRoonshiftfill`
Now each letter consists of setting some voxels and a delay, setting some other voxels, delay again etc.

Every time you do one or more statements (setvoxel, shift) that is/are followed by a delay_ms, you have two steps. The fills also count as steps. If I counted correctly, you have 57 steps.
Code: [Select]
`// effect 2 text Roonvoid Roon() {  PORTC = B10110110; // 21)  fill(0x00);    //R2)  setvoxel(0, 7, 0);  ...3)  delay_ms(5000);4)  setvoxel(0, 7, 4);  ...5)  delay_ms(5000);6)  setvoxel(0, 7, 3);  ...  shift(AXIS_X, 1);7)  delay_ms(5000);8)  setvoxel(0, 7, 0);  ...  shift(AXIS_X, 1);9)  delay_ms(5000);10)  shift(AXIS_X, 1);11)  delay_ms(6000);  //o12)  setvoxel(0, 7, 1);  ...  shift(AXIS_X, 1);13)  delay_ms(5000);14)  setvoxel(0, 7, 0);  ...  shift(AXIS_X, 1);15)  delay_ms(5000);16)  setvoxel(0, 7, 0);  ...  shift(AXIS_X, 1);17)  delay_ms(5000);18)  setvoxel(0, 7, 1);  ...  shift(AXIS_X, 1);19)  delay_ms(5000);20)  shift(AXIS_X, 1);21)  delay_ms(6000);  //o21)  setvoxel(0, 7, 1);  ...  shift(AXIS_X, 1);22)  delay_ms(5000);23)  setvoxel(0, 7, 4);  ...  shift(AXIS_X, 1);24)  delay_ms(5000);25)  setvoxel(0, 7, 4);  ...  shift(AXIS_X, 1);26)  delay_ms(5000);27)  setvoxel(0, 7, 1);  ...  shift(AXIS_X, 1);28)  delay_ms(5000);29)  shift(AXIS_X, 1);30)  delay_ms(6000);  //n31)  setvoxel(0, 7, 0);  ...  shift(AXIS_X, 1);32)  delay_ms(5000);33)  setvoxel(0, 7, 4);  shift(AXIS_X, 1);34)  delay_ms(5000);35)  setvoxel(0, 7, 4);  shift(AXIS_X, 1);36)  delay_ms(5000);37)  setvoxel(0, 7, 0);  ...  shift(AXIS_X, 1);38)  delay_ms(5000);39)  shift(AXIS_X, 1);40)  delay_ms(6000);41)  shift(AXIS_X, 1);42)  delay_ms(5000);43)  shift(AXIS_X, 1);44)  delay_ms(5000);45)  shift(AXIS_X, 1);46)  delay_ms(5000);47)  shift(AXIS_X, 1);48)  delay_ms(5000);49)  shift(AXIS_X, 1);50)  delay_ms(5000);51)  shift(AXIS_X, 1);52)  delay_ms(5000);53)  shift(AXIS_X, 1);54)  delay_ms(5000);55)  shift(AXIS_X, 1);56)  delay_ms(3500);57)  fill(0x00);}`
I do not understand why you did not implement steps 39 to 56 in e.g. a for-loop; maybe inexperience.
E.g.
Code: [Select]
`// shift 7 times with a delay of 5000for(int cnt=0;cnt<7;cnt++){  shift(AXIS_X,1);  delay_ms(5000);}// shift one more with a delay of 3500shift(AXIS_X,1);delay_ms(5000);`
Anyway, that does not matter too much.

A simple way to implement a state machine is the use of a switch/case construction.
Code: [Select]
`/*  display Roon  Returns:    true if completed, else false*/bool effect_Roon(){  // remember what we are going to do  static byte currentState = 1;    switch(currentState)  {    case 1:      fill(0x00);      // done with this state, next time we call effect_Roon do the next step      currentState++;      break;    case 2:      setvoxel(0, 7, 0);      setvoxel(0, 7, 1);      setvoxel(0, 7, 2);      setvoxel(0, 7, 3);      setvoxel(0, 7, 4);      setvoxel(0, 7, 5);      setvoxel(0, 7, 6);      setvoxel(0, 7, 7);      shift(AXIS_X, 1);      // done with this state, next time we call effect_Roon do the next step      currentState++;      break;    case 3:      delay_ms(5000);      // done with this state, next time we call effect_Roon do the next step      currentState++;      break;    case 4:      setvoxel(0, 7, 4);      setvoxel(0, 7, 7);      shift(AXIS_X, 1);      currentState++;      break;    case 5:      delay_ms(5000);      currentState++;      break;    ...    ...    case 57:      fill(0x00);      // done with this state, next time we call effect_Roon do first step      currentState=0;      // indicate that the effect is finished      return true;  }  // indicate that effect is in progress  return true;}`
Note that I have renamed Roon to effect_roon for a more consistent naming with other effects.

Because of all the delay_ms calls, we will end up with the 57 states. We can reduce this by roughly 50% if we dedicate one state to delay. For this, I'm going to reserve a number of numbers (1..10); this allows for a bit of growth if needed; the normal cases will start at 11. To make this work, you need to remember where to go after the delay; you also need to setup a delay duration.
Code: [Select]
`#define ROON_DELAYSTATE 1/*  display Roon  Returns:    true if completed, else false*/bool effect_Roon(){  // remember what we are going to do; now start at 11  static byte currentState = 11;  // where to go after a delay  static byte stateAfterDelay = 0;  // we will also keep a variable for the required delay duration  static unsigned long delayDuration;    switch(currentState)  {    case ROON_DELAYSTATE:      delay_ms(delayDuration);      // next time effect_roon is called, execute the indicated step      currentState = stateAfterDelay;      break;    case 11:      fill(0x00);      // done with this state, next time we call effect_Roon do the next step      currentState++;      break;    case 12:      setvoxel(0, 7, 0);      setvoxel(0, 7, 1);      setvoxel(0, 7, 2);      setvoxel(0, 7, 3);      setvoxel(0, 7, 4);      setvoxel(0, 7, 5);      setvoxel(0, 7, 6);      setvoxel(0, 7, 7);      shift(AXIS_X, 1);      // we're going to do a delay after this step; remember which step we want to do after the delay      stateAfterDelay = currentState + 1;      // set delay duration to 5000      delayDuration = 5000;      // done with this state, next time we call effect_Roon, do a delay      currentState = ROON_DELAYSTATE;      break;    case 13:      setvoxel(0, 7, 4);      setvoxel(0, 7, 7);      shift(AXIS_X, 1);      // setup the delay step      stateAfterDelay = currentState + 1;      delayDuration = 5000;      currentState = ROON_DELAYSTATE;      break;    case 14:      setvoxel(0, 7, 3);      setvoxel(0, 7, 4);      setvoxel(0, 7, 7);      shift(AXIS_X, 1);      // setup the delay step      stateAfterDelay = currentState + 1;      delayDuration = 5000;      currentState = ROON_DELAYSTATE;      break;    ...    ...    case xx:      fill(0x00);      // done with this state, next time we call effect_Roon do first step      currentState=0;      break;  }}`
Now, in state 12 (was state 2), we first prepare for the delay. We remember that we need to go to state 13 after the delay, we specify the delay duration and next instead of incrementing the step, we set the step to be the delay step.

In the delay step, we call delay_ms and once that's finished we set the step to the stateAfterDelay variable.

Now basically the only thing left is to implement a non-blocking delay using millis() replacing delay_ms.
Code: [Select]
`/*  non-blocking delay; call repetitively  In:    delay in milliseconds  Returns:    true if duration has lapsed, else false*/bool delayMS(unsigned long duration){  // remember when the delay was started  static unsigned long delayStartTime;  // remember if delay in progress  static bool inProgress = false;    // if delay is not in progress, 'start' it  if(inProgress == false)  {    inProgress = true;    delayStartTime = currentTime;  }    if(currentTime - delayStartTime >= duration)  {    inProgress = false;    // indicate that duration has lapsed    return true;  }  else  {    // indicate that delay is not finished yet    return false;  }}`
You can use this in the ROON_DELAYSTATE as shown below
Code: [Select]
`    case ROON_DELAYSTATE:      // if duration lapsed      if(delayMS(delayDuration) == true)      {        // next time effect_roon is called, execute the indicated step        currentState = stateAfterDelay;      }      else      {        // if the delay did not lapse yet, we stay in the same state      }      break;`

I would probably not set effect_roon up this way, but this is easier for you to follow as it better follows your original. Unfortunately a lot of cases inside the switch.

delayMS is tested, the rest as a guide line to get you started.
If you understand an example, use it.
If you don't understand an example, don't use it.

Electronics engineer by trade, software engineer by profession. Trying to get back into electronics after 15 years absence.

#### Roonie #27
##### Apr 02, 2018, 11:19 am
Yes yes,

I also have `changed` one of the effects, like you did with the `rain` effect. It was a lot of
trial and error but it works now, as a stand alone and also in my `big `sketch`.

Have a look at the sketch mayby there is something that can be beter, it`s probably
not the best or neatest coding but it gets the job done.... again thx for explaining it al ..... Now I`ll see if there are others that can also be `changed` like that, then I`ll have a look
at the state machine thing .....

#### Roonie #28
##### Apr 11, 2018, 04:32 pm Wel you really explained the `state machine`good ..... I also got that one working.
Now I only have two effects left . The effect boxside and jumping box .. Haven`t got a good look at them yet .......
This reprogramming is taking up a long time ... but it`s worth it.

thankx again

#### Roonie #29
##### Apr 13, 2018, 01:00 pm
If you don't understand, ask. I will try to explain.

I think I mentioned state machine for the more complicated effects. When you get there, shout.

HELP .......

Now I`m a bit stuck ... very stuck actually. Like I said, I only have these two effects left to `change` but I have no idea how ....

Tried both the methodes you suggested the best way I could (probally wrong ) but no joy.

Roon,

Go Up