Go Down

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

sterretje

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

Okè thankx,

here is the code so far .....




Ronald

sterretje

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

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 scope

Dit rapport zou meer informatie bevatten met
"Uitgebreide uitvoer weergeven tijden compilatie"
optie aan in Bestand -> Voorkeuren.



thankx

sterretje

#19
Mar 29, 2018, 06:45 pm Last 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 8)

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 pm Last Edit: Mar 29, 2018, 10:48 pm by Roonie
Oh damn .....  :smiley-confuse:

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 ....  :smiley-confuse:

I think the code is not `looping` but why I do not know....



sterretje

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 am Last 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 = 0
iteration =   0
rnd_num = 3
rnd_x = 1
rnd_y = 1
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 2
rnd_y = 2
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 0
rnd_y = 0
setvoxel(rnd_x, rnd_y, 7)
shift(AXIS_Z, -1          <<<<<<< little bug in the code here, missing ')'

currentTime = 1021
iteration =   1
rnd_num = 2
rnd_x = 3
rnd_y = 5
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 0
rnd_y = 5
setvoxel(rnd_x, rnd_y, 7)
shift(AXIS_Z, -1

currentTime = 2039
iteration =   2
rnd_num = 0
shift(AXIS_Z, -1

currentTime = 3040
iteration =   3
rnd_num = 2
rnd_x = 3
rnd_y = 7
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 7
rnd_y = 1
setvoxel(rnd_x, rnd_y, 7)
shift(AXIS_Z, -1

currentTime = 4058
iteration =   4
rnd_num = 0
shift(AXIS_Z, -1

currentTime = 5058
iteration =   5
rnd_num = 0
shift(AXIS_Z, -1

currentTime = 6060
iteration =   6
rnd_num = 3
rnd_x = 1
rnd_y = 5
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 5
rnd_y = 0
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 5
rnd_y = 3
setvoxel(rnd_x, rnd_y, 7)
shift(AXIS_Z, -1

currentTime = 7086
iteration =   7
rnd_num = 2
rnd_x = 0
rnd_y = 7
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 1
rnd_y = 2
setvoxel(rnd_x, rnd_y, 7)
shift(AXIS_Z, -1

currentTime = 8102
iteration =   8
rnd_num = 0
shift(AXIS_Z, -1

currentTime = 9104
iteration =   9
rnd_num = 3
rnd_x = 2
rnd_y = 1
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 3
rnd_y = 5
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 3
rnd_y = 5
setvoxel(rnd_x, rnd_y, 7)
shift(AXIS_Z, -1

currentTime = 10130
iteration =   10
rnd_num = 3
rnd_x = 0
rnd_y = 1
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 0
rnd_y = 5
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 1
rnd_y = 4
setvoxel(rnd_x, rnd_y, 7)
shift(AXIS_Z, -1

currentTime = 11156
iteration =   11
rnd_num = 3
rnd_x = 2
rnd_y = 5
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 1
rnd_y = 1
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 4
rnd_y = 0
setvoxel(rnd_x, rnd_y, 7)
shift(AXIS_Z, -1

currentTime = 12182
iteration =   12
rnd_num = 0
shift(AXIS_Z, -1

currentTime = 13184
iteration =   13
rnd_num = 2
rnd_x = 4
rnd_y = 4
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 2
rnd_y = 7
setvoxel(rnd_x, rnd_y, 7)
shift(AXIS_Z, -1

currentTime = 14201
iteration =   14
rnd_num = 2
rnd_x = 2
rnd_y = 5
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 0
rnd_y = 1
setvoxel(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 second
iteration =   14
rnd_num = 2
rnd_x = 2
rnd_y = 5
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 0
rnd_y = 1
setvoxel(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 = 0
iteration =   0
rnd_num = 3
rnd_x = 1
rnd_y = 1
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 2
rnd_y = 2
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 0
rnd_y = 0
setvoxel(rnd_x, rnd_y, 7)
shift(AXIS_Z, -1)

currentTime = 1000
iteration =   1
rnd_num = 2
rnd_x = 3
rnd_y = 5
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 0
rnd_y = 5
setvoxel(rnd_x, rnd_y, 7)
shift(AXIS_Z, -1)

currentTime = 2000
iteration =   2
rnd_num = 0
shift(AXIS_Z, -1)

currentTime = 3000
iteration =   3
rnd_num = 2
rnd_x = 3
rnd_y = 7
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 7
rnd_y = 1
setvoxel(rnd_x, rnd_y, 7)
shift(AXIS_Z, -1)

currentTime = 4000
iteration =   4
rnd_num = 0
shift(AXIS_Z, -1)

currentTime = 5000
iteration =   5
rnd_num = 0
shift(AXIS_Z, -1)

currentTime = 6000
iteration =   6
rnd_num = 3
rnd_x = 1
rnd_y = 5
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 5
rnd_y = 0
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 5
rnd_y = 3
setvoxel(rnd_x, rnd_y, 7)
shift(AXIS_Z, -1)

currentTime = 7000
iteration =   7
rnd_num = 2
rnd_x = 0
rnd_y = 7
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 1
rnd_y = 2
setvoxel(rnd_x, rnd_y, 7)
shift(AXIS_Z, -1)

currentTime = 8000
iteration =   8
rnd_num = 0
shift(AXIS_Z, -1)

currentTime = 9000
iteration =   9
rnd_num = 3
rnd_x = 2
rnd_y = 1
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 3
rnd_y = 5
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 3
rnd_y = 5
setvoxel(rnd_x, rnd_y, 7)
shift(AXIS_Z, -1)

currentTime = 10000
iteration =   10
rnd_num = 3
rnd_x = 0
rnd_y = 1
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 0
rnd_y = 5
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 1
rnd_y = 4
setvoxel(rnd_x, rnd_y, 7)
shift(AXIS_Z, -1)

currentTime = 11000
iteration =   11
rnd_num = 3
rnd_x = 2
rnd_y = 5
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 1
rnd_y = 1
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 4
rnd_y = 0
setvoxel(rnd_x, rnd_y, 7)
shift(AXIS_Z, -1)

currentTime = 12000
iteration =   12
rnd_num = 0
shift(AXIS_Z, -1)

currentTime = 13000
iteration =   13
rnd_num = 2
rnd_x = 4
rnd_y = 4
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 2
rnd_y = 7
setvoxel(rnd_x, rnd_y, 7)
shift(AXIS_Z, -1)

currentTime = 14000
iteration =   14
rnd_num = 2
rnd_x = 2
rnd_y = 5
setvoxel(rnd_x, rnd_y, 7)
rnd_x = 0
rnd_y = 1
setvoxel(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

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

Wow .. super thankx,

That`s a lot to learn...  :o
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

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

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]

fill
R
o
o
n
shift
fill

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 Roon
void Roon() {

  PORTC = B10110110; // 2

1)
  fill(0x00);
 
  //R
2)
  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);
  //o
12)
  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);
  //o
21)
  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);
  //n
31)
  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 5000
for(int cnt=0;cnt<7;cnt++)
{
  shift(AXIS_X,1);
  delay_ms(5000);
}
// shift one more with a delay of 3500
shift(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

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....  8)

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

 :)

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 .. :smiley-confuse:

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

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. :smiley-confuse:
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