Arduino Forum

Using Arduino => Programming Questions => Topic started by: Roonie on Mar 23, 2018, 03:21 pm

Title: IRremote for my 8x8x8 led cube on the mega
Post by: Roonie on Mar 23, 2018, 03:21 pm
Hi,

In an other post  (https://forum.arduino.cc/index.php?topic=535514.0)I got my 8x8x8 led cube working on the Mega.
Now as stated by J-M-L ;
Remember that capturing IR remote control signal will depend on interrupt working at a fairly high rate (receiver class which uses the 50 microsec interrupt timer to poll the input pin) so might fail..

There are various library for polling or using interrupts to explore but you'll be likely challenged if you want to keep the same refresh rate for your cube
I seem to get an `exit status 1` error when trying to use the IRRemote libary.
How can I get the IR reciever to work ??  :smiley-confuse:

Ronald

p.s.
I attached the code below as it is too big the post here.
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: groundFungus on Mar 23, 2018, 03:32 pm
Can you post the entire error message?  Usually there is more information in the error message like the cause of the error, which file the error is in, line number...
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: Roonie on Mar 23, 2018, 04:56 pm
Hello,

Sorry that`s all it says
`exit status 1` error when trying to compile.
When I remove the IRremote.sh libary it compiles just fine....
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: sterretje on Mar 23, 2018, 05:10 pm
No, scroll through the output window to see more.

I suspect that you have an interrupt conflict, something with vector 7 ?
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: Roonie on Mar 23, 2018, 05:18 pm
You are correct.. I copied the error (using the button in the IDE software) and pasted it below...


Code: [Select]
Arduino: 1.8.5 (Windows 7), Board:"Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)"

Archiving built core (caching) in: C:\Users\Roonie\AppData\Local\Temp\arduino_cache_56807\core\core_arduino_avr_mega_cpu_atmega2560_b916ae8a410cc596c9c025326ffecd11.a
libraries\z3t0-Arduino-IRremote-20a4d97\IRremote.cpp.o (symbol from plugin): In function `MATCH(int, int)':

(.text+0x0): multiple definition of `__vector_13'

sketch\Roon_cube_Mega.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here

c:/users/roonie/appdata/local/arduino15/packages/arduino/tools/avr-gcc/4.9.2-atmel3.5.4-arduino2/bin/../lib/gcc/avr/4.9.2/../../../../avr/bin/ld.exe: Disabling relaxation: it will not work with multiple definitions

collect2.exe: error: ld returned 1 exit status

exit status 1
Fout bij het compileren voor board Arduino/Genuino Mega or Mega 2560

Dit rapport zou meer informatie bevatten met
"Uitgebreide uitvoer weergeven tijden compilatie"
optie aan in Bestand -> Voorkeuren.
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: sterretje on Mar 23, 2018, 06:21 pm
If you search for my username in combination with interrupt conflict, you will find a few threads with guides to solve it; also one in the Dutch section ;) Note that guides are for the 328P processor nbut the approach is the same.

E.g. https://forum.arduino.cc/index.php?topic=454873.0 (https://forum.arduino.cc/index.php?topic=454873.0)

It applies to Ken's IRremote library. I posted in another thread recently; there seems to be a change and there is now a new file that needs to be modified (something with boards if not mistaken).
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: Roonie on Mar 23, 2018, 09:38 pm
Lots of reading and searching but I got the sketch to compile without any errors.
I changed the boarddefs.h file where you can state which timer for which processor you want to use.
I know that TIMER2 is an 8bit and the rest are 16bit timers. I changed it to the option TIMER1.

Only problem is that I still can`t seem to recieve any ir signals using the serial monitor.
I`m using a pronto remote with codes that did work with the Uno with the same IR reciever.

On the Mega I`m using pin D21 don`t know if that also has to be changed in the IRremote libary files ? :smiley-confuse:  


Code: [Select]
#define dim 20
#define IRactive 39
#define IRpin 21
IRrecv irrecv(IRpin);
decode_results IRresults;

int current_effect;
int digit;
int auto_run;
int run_speed;
int run_time;

volatile unsigned char cube[8][8];
volatile int current_layer = 0;

void setup()
{
  digit = 0;
  
  pinMode(dim,OUTPUT);
  pinMode(IRactive,OUTPUT);
  pinMode(IRpin, INPUT);

  
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the IR receiver
 


and

Code: [Select]
void loop()  //ALL VISUAL EFFECTS ARE STARTED FROM HERE
{
 if (irrecv.decode(&IRresults)) {
    Serial.println(IRresults.value, DEC); // Print the Serial 'results.value'
    irrecv.resume();   // Receive the next value
 }
 



Thankx for your time ......

Ronald


p.s.
updated .ino file and the IR libary used (unchanged) added below
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: sterretje on Mar 24, 2018, 04:25 am
Can you attach your updated boarddefs.h file so we can see what you've changed?

As far as I can see, there is no need to change anything else. The receive functionality uses the specified timer to check every 50 us if the IR signal is HIGH or LOW and uses a digitaRead. Below from IRremote.cpp
Code: [Select]
//+=============================================================================
// Interrupt Service Routine - Fires every 50uS
// TIMER2 interrupt code to collect raw data.
// Widths of alternating SPACE, MARK are recorded in rawbuf.
// Recorded in ticks of 50uS [microseconds, 0.000050 seconds]
// 'rawlen' counts the number of entries recorded so far.
// First entry is the SPACE between transmissions.
// As soon as a the first [SPACE] entry gets long:
//   Ready is set; State switches to IDLE; Timing of SPACE continues.
// As soon as first MARK arrives:
//   Gap width is recorded; Ready is cleared; New logging starts
//
#ifdef IR_TIMER_USE_ESP32
void IRTimer()
#else
ISR (TIMER_INTR_NAME)
#endif
{
TIMER_RESET;

// Read if IR Receiver -> SPACE [xmt LED off] or a MARK [xmt LED on]
// digitalRead() is very slow. Optimisation is possible, but makes the code unportable
uint8_t  irdata = (uint8_t)digitalRead(irparams.recvpin);

I suspect that the comment mentioning TIMER2 is something that was never updated; possibly the very first version(s) of the library only supported TIMER2.
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: Roonie on Mar 24, 2018, 09:17 am
added the file to the post above ......


Ronald
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: sterretje on Mar 24, 2018, 11:23 am
OK, the only change is the one from timer2 to timer1 for the Megas. That should do the trick as far as I know.

Options:
1)
We did something wrong; no idea what
2a)
Test your sensor on the Uno with boarddefs as it currently is; does it work? This will prove that your sensor is still OK.
2b)
Test your sensor on the Uno with boarddefs modified to use Timer1 instead of Timer2 (line 152/153); does it work? That basically would proof that the approach works.
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: Roonie on Mar 24, 2018, 12:59 pm
I think I know what the problem is ... I think the program just `loops` everytime the `patern effect` is finished.
What I need is a loop just for the IR.... but how ??

That`s excatly whats happening, I put the `irrecv.decode` line somewhere else
and everytime the cube effect changed, the code ran past that line and the result was printed.

But I need the IR to recieve all the time ... not just when the code changes the cube effect. So how do I create a loop for that?
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: sterretje on Mar 24, 2018, 04:14 pm
Try to confirm with some simple Mega code (one of the examples that come with the library) without the cube effects to see if IR works. You should not "think you know what the problem is"; you need to know for sure before you continue.

If you need immediate reaction, get rid of all the delays and replace them by a millis() based approach.

It will be a lot of work as you need to break up all your cube functions in little steps. The simplest one to demonstrate how to get rid of delay_ms is probably effect_rain. It contains a nested for-loop. The inner loop does not pose an issue but the outer loop loop 100 times and hence 100 seconds delay.

This would be a reworked version to demonstrate how you can get rid of delay_ms; code not tested.
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;
  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;
}


Other functions are more complicated. For the effect_intro, you will need a state machine to be able to keep track which step you are executing.

In loop(), simply call effect_rain and check for IR
Code: [Select]
void loop()
{
  if (irrecv.decode(&IRresults))
  {
    Serial.println(IRresults.value, DEC); // Print the Serial 'results.value'
    irrecv.resume();   // Receive the next value
  }
  effect_rain()
}


Now running out of time. See if you can understand state machines.
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: Roonie on Mar 24, 2018, 04:43 pm
Thankx man .....  :o

More work for me ......

At least I got it kind of working now with a bit of a delay .....  >:(

But I`ll definitely try what you suggest. Although I looks quite difficult.


Ronald,



Super bedankt nogmaals ........  :)

Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: sterretje on Mar 24, 2018, 04:50 pm
Just a different mind set ;)

I forgot to mention how to use the return value of the modified effect_rain. You can use this in loop() to determine if you can go to the next effect.
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: Roonie on Mar 27, 2018, 04:01 pm
Hi,

I tried replacing the effect_rain code with yours... but no joy  :smiley-confuse:
Trying to compile I got the error;
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:914: error: 'currentTime' was not declared in this scope

     lastUpdateTime = currentTime;

                      ^

Roon_cube_Mega:926: error: 'currentTime' was not declared in this scope

   if (currentTime - lastUpdateTime >= 1000)

       ^

exit status 1
'currentTime' was not declared in this scope

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

As I don`t yet know how the code works I can`t say or see whats wrong.
Big learning curve.....  :o

Ronald
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: sterretje on 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.
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: Roonie on Mar 28, 2018, 05:00 pm
Okè thankx,

here is the code so far .....




Ronald
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: sterretje on 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.
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: Roonie on 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 scope

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



thankx
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: sterretje on Mar 29, 2018, 06:45 pm
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);
    }
  }
}
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: Roonie on Mar 29, 2018, 09:05 pm
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....


Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: sterretje on 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.
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: sterretje on Mar 30, 2018, 05:32 am
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.
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: sterretje on 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))
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: Roonie on Mar 30, 2018, 11:01 pm
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
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: sterretje on 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.


Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: sterretje on 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]

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.
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: Roonie on 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....  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 .....
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: Roonie on 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 .. :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
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: Roonie on 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. :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,
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: sterretje on Apr 14, 2018, 10:51 am
It will take a bit of time. Can you add your attempt for the jumping box?
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: Roonie on Apr 14, 2018, 04:00 pm
Hi ...

Uh ... well ....

  As I didn`t know which methode would be best which to use, the state machine or the currentTime thing I tried both a bit (for about 5 hours  :o ) but finally gave up. At first the state machine with the switch and case look promissing but halfway the effect the delay was put in the for loop instead of after like the first few. This gave me a bit of a headache....  :smiley-confuse:

  And the currentTime thing I still don`t really understand how the timing works even though I have used it on others effects (space and wormsqueeze) succesfully and also how to use it in the for loop to get rid of the delay.....
  Now mayby they are both not suited for the job and there is an otherway. So after a while I thought it was time to ask for some help. But I don`t have any sketches  :(



Roon,
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: sterretje on Apr 14, 2018, 04:19 pm
By the looks of it, state machine is the correct approach. I'm working on an example for the jumping box.

For the loops, you can use an additional counter (static variable); stay in the same atate till you have done the number of iterations.

I will also explain the currentTime approach.
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: sterretje on Apr 14, 2018, 07:41 pm
First the timing  (currentTime). The general approach is possibly most easily explained with the analogy of boiling an egg. You put an egg in water and start boiling it. When you put the egg in the water, you look on the clock to check what the time is; this is the delayStartTime in the delayMS function. Now you go and do something else and on a regular you look on the clock and check if e.g. 4 minutes have lapsed. If not, you continue doing something else again and so on. While the time has not lapsed, delayMS will return false because the egg is not done yet.

Eventually the 4 minutes have lapsed and if (currentTime - delayStartTime >= duration) will evaluate to true and you know that your egg is done. delayMS will return true when your egg is done.

I needed an additional variable so when the delay starts, the code can set the delayStartTime to the current time; if inProgress equals false, we will set the delayStartTime (this is, when you start boiling the egg). As we now have set the delayStartTime, we set the inProgress flag to true so the next time we call delayMS it will not set the delayStartTime again.

Once the 4 minutes have passed, we set inProgress to false so the next time we call delayMS (e.g. you decide to boil another egg) it will look on the clock again to remember the delayStartTime.

I hope that clarifies how it works.

Now to the effect_jumping_box.

I'm going to use a slightly different approach for effect_jumping_box and make use of a few functions that can be called in your jumping box state machine. Analysing your code, I've put the function calls where I see the different states (below identified by >> at the beginning of the line). All function calls for this start with jb (for jumping box).

Code: [Select]
void effect_jumping_box()
{

  // digitalWrite(dp_left,LOW);      // extra effect options off
  // options = 0;
  if (random_run == 1)
  {
    random2 = 2;
  }

  PORTC = B10110110; // display on 2

  int cnt, cnt_2, time;

  //Bottom To Top
>>  jbBottomToTop();
  for (cnt = 0; cnt <= 7; cnt++)
  {
    box_wireframe(0, 0, 0, 7, 7, cnt);
    delay_ms(2000);
  }

  for (cnt = 0; cnt < 7; cnt++)
  {
    clrplane_z(cnt);
    delay_ms(2000);
  }

  //Shift Things Right
>>  jbShiftThingsRight();
  //1
  shift(AXIS_Y, -1);
  for (cnt = 0; cnt <= 7; cnt++)
  {
    setvoxel(cnt, 0, 6);
  }
  delay_ms(2000);
  //2
  shift(AXIS_Y, -1);
  for (cnt = 0; cnt <= 7; cnt++)
  {
    setvoxel(cnt, 0, 5);
  }
  setvoxel(0, 0, 6);
  setvoxel(7, 0, 6);
  delay_ms(2000);
  //3
  shift(AXIS_Y, -1);
  for (cnt = 0; cnt <= 7; cnt++)
  {
    setvoxel(cnt, 0, 4);
  }
  setvoxel(0, 0, 5);
  setvoxel(7, 0, 5);
  setvoxel(0, 0, 6);
  setvoxel(7, 0, 6);
  delay_ms(2000);

  //4
  shift(AXIS_Y, -1);
  for (cnt = 0; cnt <= 7; cnt++)
  {
    setvoxel(cnt, 0, 3);
  }
  setvoxel(0, 0, 4);
  setvoxel(7, 0, 4);
  setvoxel(0, 0, 5);
  setvoxel(7, 0, 5);
  setvoxel(0, 0, 6);
  setvoxel(7, 0, 6);
  delay_ms(2000);

  //5
  shift(AXIS_Y, -1);
  for (cnt = 0; cnt <= 7; cnt++)
  {
    setvoxel(cnt, 0, 2);
  }
  setvoxel(0, 0, 3);
  setvoxel(7, 0, 3);
  setvoxel(0, 0, 4);
  setvoxel(7, 0, 4);
  setvoxel(0, 0, 5);
  setvoxel(7, 0, 5);
  setvoxel(0, 0, 6);
  setvoxel(7, 0, 6);
  delay_ms(2000);

  //6
  shift(AXIS_Y, -1);
  for (cnt = 0; cnt <= 7; cnt++)
  {
    setvoxel(cnt, 0, 1);
  }
  setvoxel(0, 0, 2);
  setvoxel(7, 0, 2);
  setvoxel(0, 0, 3);
  setvoxel(7, 0, 3);
  setvoxel(0, 0, 4);
  setvoxel(7, 0, 4);
  setvoxel(0, 0, 5);
  setvoxel(7, 0, 5);
  delay_ms(2000);

  //7
  shift(AXIS_Y, -1);
  for (cnt = 0; cnt <= 7; cnt++)
  {
    setvoxel(cnt, 0, 0);
  }
  setvoxel(0, 0, 1);
  setvoxel(7, 0, 1);
  setvoxel(0, 0, 2);
  setvoxel(7, 0, 2);
  setvoxel(0, 0, 3);
  setvoxel(7, 0, 3);
  setvoxel(0, 0, 4);
  setvoxel(7, 0, 4);
  setvoxel(0, 0, 5);
  setvoxel(7, 0, 5);
  delay_ms(2000);


  //Right To Left
>>  jbRightToLeft();
  
  for (cnt = 0; cnt <= 7; cnt++)
  {
    box_wireframe(0, 0, 0, 7, cnt, 7);
    delay_ms(2000);
  }
  for (cnt = 0; cnt < 7; cnt++)
  {
    clrplane_y(cnt);
    delay_ms(2000);
  }

  //Shift to the bottom
>>  jbShiftToBottom();
  for (cnt_2 = 6; cnt_2 >= 0; cnt_2--)
  {
    shift(AXIS_Z, -1);
    for (cnt = 0; cnt <= 7; cnt++)
    {
      setvoxel(cnt, cnt_2, 0);
    }
    for (cnt = 6; cnt > cnt_2; cnt--)
    {
      setvoxel(0, cnt, 0);
      setvoxel(7, cnt, 0);
    }

    delay_ms(2000);
  }


  //Make All Wall Box
>>  jbMakeAllWallBox();
  for (cnt = 0; cnt <= 6; cnt++)
  {
    fill(0x00);
    box_walls(0, 0, 0, 7, 7, cnt);
    delay_ms(2000);
  }

  jbResizeBox();
  time = 2000;
  for (cnt_2 = 0; cnt_2 < 5; cnt_2++)
  {
    time = time - 300;
    //Make Box Smaller
    for (cnt = 0; cnt <= 3; cnt++)
    {
      fill(0x00);
      box_walls(cnt, cnt, cnt, 7 - cnt, 7 - cnt, 7 - cnt);
      delay_ms(time);
    }

    //Make Box Bigger
    for (cnt = 0; cnt <= 3; cnt++)
    {
      fill(0x00);
      box_walls(3 - cnt, 3 - cnt, 3 - cnt, 4 + cnt, 4 + cnt, 4 + cnt);
      delay_ms(time);
    }
  }

>>  jbNoIdea();
  for (cnt_2 = 0; cnt_2 < 5; cnt_2++)
  {
    time = time + 300;
    //Make Box Smaller
    for (cnt = 0; cnt <= 3; cnt++)
    {
      fill(0x00);
      box_walls(cnt, cnt, cnt, 7 - cnt, 7 - cnt, 7 - cnt);
      delay_ms(time);
    }
  }
}


Add empty functions after effect_jumping_box.

Code: [Select]
// ==========================================================================================
// jumping box functions                                                                   ==
// ==========================================================================================

/*
  jumping box effect: build a box from bottom to top
  Returns:
    true once completed, else false
*/
bool jbBottomToTop()
{

}

/*
  jumping box effect: shift the box to the right
  Returns:
    true once completed, else false
*/
bool jbShiftThingsRight()
{

}

/*
  jumping box effect: shift the box from the right to the left
  Returns:
    true once completed, else false
*/
bool jbRightToLeft()
{

}

/*
  jumping box effect: shift the box to the bottom
  Returns:
    true once completed, else false
*/
bool jbShiftToBottom()
{

}

/*
  jumping box effect: draw a box with all walls
  Returns:
    true once completed, else false
*/
bool jbMakeAllWallBox()
{

}

/*
  jumping box effect: resize the box
  Returns:
    true once completed, else false
*/
bool jbResizeBox()
{

}

/*
  jumping box effect: I have no idea what this exactly does
  Returns:
    true once completed, else false
*/
bool jbNoIdea()
{

}

You can give better descriptions in the comment blocks of each function as you can exactly see what each part of the effect does.

Next you can move the current functionalities to those functions as shown in the next post.
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: sterretje on Apr 14, 2018, 07:42 pm
Code: [Select]
// ==========================================================================================
// jumping box variables and functions                                                     ==
// ==========================================================================================

// because this is used in a few function, it's a global variable; used to be time
int jbTime;

/*
  jumping box effect: build a box from bottom to top
  Returns:
    true once completed, else false
*/
bool jbBottomToTop()
{
  int cnt;

  for (cnt = 0; cnt <= 7; cnt++)
  {
    box_wireframe(0, 0, 0, 7, 7, cnt);
    delay_ms(2000);
  }

  for (cnt = 0; cnt < 7; cnt++)
  {
    clrplane_z(cnt);
    delay_ms(2000);
  }

  return true;
}

/*
  jumping box effect: shift the box to the right
  Returns:
    true once completed, else false
*/
bool jbShiftThingsRight()
{
  int cnt;

  //1
  shift(AXIS_Y, -1);
  for (cnt = 0; cnt <= 7; cnt++)
  {
    setvoxel(cnt, 0, 6);
  }
  delay_ms(2000);
  //2
  shift(AXIS_Y, -1);
  for (cnt = 0; cnt <= 7; cnt++)
  {
    setvoxel(cnt, 0, 5);
  }
  setvoxel(0, 0, 6);
  setvoxel(7, 0, 6);
  delay_ms(2000);
  //3
  shift(AXIS_Y, -1);
  for (cnt = 0; cnt <= 7; cnt++)
  {
    setvoxel(cnt, 0, 4);
  }
  setvoxel(0, 0, 5);
  setvoxel(7, 0, 5);
  setvoxel(0, 0, 6);
  setvoxel(7, 0, 6);
  delay_ms(2000);

  //4
  shift(AXIS_Y, -1);
  for (cnt = 0; cnt <= 7; cnt++)
  {
    setvoxel(cnt, 0, 3);
  }
  setvoxel(0, 0, 4);
  setvoxel(7, 0, 4);
  setvoxel(0, 0, 5);
  setvoxel(7, 0, 5);
  setvoxel(0, 0, 6);
  setvoxel(7, 0, 6);
  delay_ms(2000);

  //5
  shift(AXIS_Y, -1);
  for (cnt = 0; cnt <= 7; cnt++)
  {
    setvoxel(cnt, 0, 2);
  }
  setvoxel(0, 0, 3);
  setvoxel(7, 0, 3);
  setvoxel(0, 0, 4);
  setvoxel(7, 0, 4);
  setvoxel(0, 0, 5);
  setvoxel(7, 0, 5);
  setvoxel(0, 0, 6);
  setvoxel(7, 0, 6);
  delay_ms(2000);

  //6
  shift(AXIS_Y, -1);
  for (cnt = 0; cnt <= 7; cnt++)
  {
    setvoxel(cnt, 0, 1);
  }
  setvoxel(0, 0, 2);
  setvoxel(7, 0, 2);
  setvoxel(0, 0, 3);
  setvoxel(7, 0, 3);
  setvoxel(0, 0, 4);
  setvoxel(7, 0, 4);
  setvoxel(0, 0, 5);
  setvoxel(7, 0, 5);
  delay_ms(2000);

  //7
  shift(AXIS_Y, -1);
  for (cnt = 0; cnt <= 7; cnt++)
  {
    setvoxel(cnt, 0, 0);
  }
  setvoxel(0, 0, 1);
  setvoxel(7, 0, 1);
  setvoxel(0, 0, 2);
  setvoxel(7, 0, 2);
  setvoxel(0, 0, 3);
  setvoxel(7, 0, 3);
  setvoxel(0, 0, 4);
  setvoxel(7, 0, 4);
  setvoxel(0, 0, 5);
  setvoxel(7, 0, 5);
  delay_ms(2000);

  return true;
}

/*
  jumping box effect: shift the box from the right to the left
  Returns:
    true once completed, else false
*/
bool jbRightToLeft()
{
  int cnt;
  for (cnt = 0; cnt <= 7; cnt++)
  {
    box_wireframe(0, 0, 0, 7, cnt, 7);
    delay_ms(2000);
  }
  for (cnt = 0; cnt < 7; cnt++)
  {
    clrplane_y(cnt);
    delay_ms(2000);
  }

  return true;
}

/*
  jumping box effect: shift the box to the bottom
  Returns:
    true once completed, else false
*/
bool jbShiftToBottom()
{
  int cnt, cnt_2;

  for (cnt_2 = 6; cnt_2 >= 0; cnt_2--)
  {
    shift(AXIS_Z, -1);
    for (cnt = 0; cnt <= 7; cnt++)
    {
      setvoxel(cnt, cnt_2, 0);
    }
    for (cnt = 6; cnt > cnt_2; cnt--)
    {
      setvoxel(0, cnt, 0);
      setvoxel(7, cnt, 0);
    }

    delay_ms(2000);
  }

  return true;
}

/*
  jumping box effect: draw a box with all walls
  Returns:
    true once completed, else false
*/
bool jbMakeAllWallBox()
{
  int cnt;

  for (cnt = 0; cnt <= 6; cnt++)
  {
    fill(0x00);
    box_walls(0, 0, 0, 7, 7, cnt);
    delay_ms(2000);
  }
  return true;
}

/*
  jumping box effect: resize the box
  Returns:
    true once completed, else false
*/
bool jbResizeBox()
{
  int cnt, cnt_2;
  jbTime = 2000;
  for (cnt_2 = 0; cnt_2 < 5; cnt_2++)
  {
    jbTime = jbTime - 300;
    //Make Box Smaller
    for (cnt = 0; cnt <= 3; cnt++)
    {
      fill(0x00);
      box_walls(cnt, cnt, cnt, 7 - cnt, 7 - cnt, 7 - cnt);
      delay_ms(jbTime);
    }

    //Make Box Bigger
    for (cnt = 0; cnt <= 3; cnt++)
    {
      fill(0x00);
      box_walls(3 - cnt, 3 - cnt, 3 - cnt, 4 + cnt, 4 + cnt, 4 + cnt);
      delay_ms(jbTime);
    }
  }

  return true;
}

/*
  jumping box effect: I have no idea what this exactly does
  Returns:
    true once completed, else false
*/
bool jbNoIdea()
{
  int cnt, cnt_2;

  for (cnt_2 = 0; cnt_2 < 5; cnt_2++)
  {
    jbTime = jbTime + 300;
    //Make Box Smaller
    for (cnt = 0; cnt <= 3; cnt++)
    {
      fill(0x00);
      box_walls(cnt, cnt, cnt, 7 - cnt, 7 - cnt, 7 - cnt);
      delay_ms(jbTime);
    }
  }

  return true;
}


And effect_jumping_box now looks like
Code: [Select]
bool effect_jumping_box()
{

  // digitalWrite(dp_left,LOW);      // extra effect options off
  // options = 0;
  if (random_run == 1)
  {
    random2 = 2;
  }

  PORTC = B10110110; // display on 2

  //Bottom To Top
  jbBottomToTop();

  //Shift Things Right
  jbShiftThingsRight();

  //Right To Left
  jbRightToLeft();

  //Shift to the bottom
  jbShiftToBottom();

  //Make All Wall Box
  jbMakeAllWallBox();

  jbResizeBox();

  jbNoIdea();
 
  return true;
}

You might already see the state machine for effect_jumping_box taking shape. Next we can implement the state machine
Code: [Select]
/*
  jumping box effect
  Returns:
    true once completed, else false
*/
bool effect_jumping_box()
{
  // current state of the jumping box effect
  static int currentState;

  // digitalWrite(dp_left,LOW);      // extra effect options off
  // options = 0;
  if (random_run == 1)
  {
    random2 = 2;
  }

  PORTC = B10110110; // display on 2

  switch (currentState)
  {
    // Bottom To Top
    case 0:
      if (jbBottomToTop() == true)
      {
        currentState++;
      }
      break;
    // Shift Things Right
    case 1:
      if (jbShiftThingsRight() == true)
      {
        currentState++;
      }
      break;
    // Right To Left
    case 2:
      if (jbRightToLeft()() == true)
      {
        currentState++;
      }
      break;
    // Shift to the bottom
    case 3:
      if (jbShiftToBottom() == true)
      {
        currentState++;
      }
      break;
    // Make All Wall Box
    case 4:
      if (jbMakeAllWallBox() == true)
      {
        currentState++;
      }
      break;
    // resize box
    case 5:
      if (jbResizeBox() == true)
      {
        currentState++;
      }
      break;
    // no idea
    case 6:
      if (jbNoIdea() == true)
      {
        // this was the last state of the jumping box effect; reset currentState
        currentState = 0;
        // indicate that jumping box is finished
        return true;
      }
      break;
  }

  // indicate that jumping box is not finished yet
  return false;
}

Please note that there is no delay state as for the roon effect; those 'delays' will be implemented in the functions and work similar as the 'delay' in the rain effect.
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: sterretje on Apr 14, 2018, 07:43 pm
Now you can rework the functions. If you look closely at jbBottomToTop, you can see two states (the two for-loops). You can use two functions but as I have difficulty visualising wat happens on your cube, I can't come up with proper names for them and hence left it.

So with two states, we can implement them in this function
Code: [Select]
/*
  jumping box effect: build a box from bottom to top
  Returns:
    true once completed, else false
*/
bool jbBottomToTop()
{
  // current state
  static byte currentState = 0;
  // loop counter
  static byte counter = 0;

  // last time that bottom-to-top was updated
  static unsigned long lastUpdateTime;

  switch (currentState)
  {
    case 0:
      // if first time or if 'delay' lapsed
      if (counter == 0 || currentTime - lastUpdateTime > 2000)
      {
        lastUpdateTime = currentTime;

        // if we have done all steps
        if (counter == 8)
        {
          // reset counter for the next step
          counter = 0;
          // next step
          currentState = 1;
        }
        else
        {
          // draw and increment counter
          box_wireframe(0, 0, 0, 7, 7, counter++);
        }
      }
      break;
    case 1:
      // if first time or if 'delay' lapsed
      if (counter == 0 || currentTime - lastUpdateTime > 2000)
      {
        lastUpdateTime = currentTime;

        // if we have done all steps
        if (counter == 8)
        {
          // reset counter for the next time
          counter = 0;
          // next step (go back to first step)
          currentState = 0;

          // here we're done with the full bottom-to-top
          return true;
        }
        else
        {
          // draw and increment counter
          clrplane_z(counter++);
        }
      }
      break;
  }
 
  // not done yet with this part of the effect
  return false;
}


And that's it for today. Maybe more tomorrow (time permitting).
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: Roonie on Apr 18, 2018, 06:51 pm
 :o  :o  super explanation ...

thankx a lot.

I think I got it a bit  :)
I got ` jbShiftThingsRight` as you call it, also working.




Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: Roonie on Apr 18, 2018, 10:14 pm
I seem to be a bit stuck now ....

3 `jumping_box` functions have for loops in for loops..... This has me a bit puzzled????

Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: sterretje on Apr 19, 2018, 07:20 am
I thought that those nested for loops would give you a bit of gray hairs. From memory, you can create a new function for the inner loop based on the given principles; for e.g. jbResizeBox, you can call them e.g. jbMakeBoxBigger() and jbMakeBoxSmaller().

Now those functions need to know about the variable jbTime (because the inner loop uses it). One of the functions that I gave you long ago used a parameter (I think it was called iterations in effect_rain, not sure). So e.g. your jbMakeBoxBigger can look like
Code: [Select]
bool jbMakeBoxBigger(int delayTime)
{
  ...
  ...
}

and you can use dat in the compare of the times.

Next you can work on bool jbResizeBox() calling those two functions. I might have time today or else in the weekend to look further into it. There might be another approach as well.
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: Roonie on Apr 22, 2018, 12:13 pm
Yes yes ....

I got the rest of the effect to work ....
Now one last effect to go, haven`t look at it yet. Been sitting too long behind the computer as it is.

Again thankx for al your help...
Still have a couple of lillte problems to sovle  :o

So probally I`ll give you another shout again .
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: Roonie on Apr 24, 2018, 06:06 pm
Now I got them all to work with my remote....  8)

Again thankx for the help.
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: sterretje on Apr 26, 2018, 06:23 am
Gefeliciteerd :)

That's great. If you attach your complete code, I will see if I can find time to look at it and maybe rework it to a more consistent code; I showed (and used) different approaches for different problems but probably everything can be caught with one generic approach.
Title: Re: IRremote for my 8x8x8 led cube on the mega working !! video
Post by: Roonie on Apr 29, 2018, 09:47 am
Ja, dank je wel  :)


I must say I`m a bit proud of myself. But without the help of you and J-M-L in the beginning with the programming from the Uno to the Mega. I wouldn`t have been able to get it working.
Now the coding probally isn`t the neatest or effeicent, but hey it gets the job done and as they `er zijn meerdere wegen naar Rome`.  ;)
I also want to `add` some extra features like time and temperature. But for now it`s time for a bit of a rest. Also need to do some chores around my house ........

I put a video online (https://www.youtube.com/watch?v=MZRTjlcjB-c) so you can see the result......


Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: sterretje on May 01, 2018, 07:39 am
You have a few bugs in your code. In the IDE menu File -> preferences, set compiler warnings to all and compile your code. You will see plenty orange lines coming along. They are all warnings but the ones that state "warning: control reaches end of non-void function [-Wreturn-type]" need attention.

They indicate that the function at that point does not return anything so it basically 'returns' something unknown. When you check the return value in the caller, it will interpret the unknown (in the below true or false, but no-one knows what it will be). This unknown can one time be e.g. true, the other time false.

e.g. your code contains
Code: [Select]
      if (jumping_box4() == true) {
        currentState++;
      }

but one of the warnings indicates
Code: [Select]
C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino: In function 'bool jumping_box4()':

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino:1694:1: warning: control reaches end of non-void function [-Wreturn-type]

 }

 ^



Below a complete list that I get
Code: [Select]

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino: In function 'void loop()':

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino:192:7: warning: unused variable 'i' [-Wunused-variable]

   int i,x,y,z;

       ^

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino:267:13: warning: unused variable 'iir' [-Wunused-variable]

 static byte iir;

             ^

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino: In function 'bool effect_text()':

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino:1367:1: warning: no return statement in function returning non-void [-Wreturn-type]

 }

 ^

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino: In function 'bool jumping_box6()':

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino:1731:45: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]

 if (var2==1 && currentTime - lastUpdateTime > jbTime){ 

                                             ^

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino:1744:45: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]

 if (var2==2 && currentTime - lastUpdateTime > jbTime){

                                             ^

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino: In function 'bool jumping_box7()':

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino:1777:45: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]

 if (var2==1 && currentTime - lastUpdateTime > jbTime){ 

                                             ^

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino:1790:45: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]

 if (var2==2 && currentTime - lastUpdateTime > jbTime){

                                             ^

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino:1803:45: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]

 if (var2==3 && currentTime - lastUpdateTime > jbTime){ 

                                             ^

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino: In function 'void effect_random_filler()':

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino:1910:34: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]

 if (currentTime - lastUpdateTime > 4 - i){     // speed

                                  ^

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino: In function 'void effect_rain()':

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino:1983:45: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]

 if (var4==1 && currentTime - lastUpdateTime >= 90-(ii/2)){ // faster falling raindrops 

                                             ^

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino: In function 'void effect_boxside_randsend_parallel(char, int)':

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino:2182:5: warning: variable 'notdone' set but not used [-Wunused-but-set-variable]

 int notdone = 1;

     ^

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino: In function 'void effect_space()':

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino:2302:46: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]

 if  (var7==0 && currentTime - lastUpdateTime >= timing){

                                              ^

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino:2321:46: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]

 if  (var7==1 && currentTime - lastUpdateTime >= timing){    // same speed

                                              ^

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino:2340:45: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]

 if (var7==2 && currentTime - lastUpdateTime >= timing){

                                             ^

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino:2362:45: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]

 if (var7==3 && currentTime - lastUpdateTime >= timing){    // same speed   

                                             ^

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino: In function 'void effect_wormsqueeze(int, int, int)':

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino:2547:5: warning: unused variable 'i' [-Wunused-variable]

 int i,j,k,dx,dy;

     ^

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino:2550:5: warning: unused variable 't' [-Wunused-variable]

 int t = 0;

     ^

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino: In function 'void line(int, int, int, int, int, int)':

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino:3052:17: warning: variable 'lasty' set but not used [-Wunused-but-set-variable]

   unsigned char lasty,lastz;

                 ^

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino:3052:23: warning: variable 'lastz' set but not used [-Wunused-but-set-variable]

   unsigned char lasty,lastz;

                       ^

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino: In function 'bool jumping_box4()':

C:\Users\sterretje\Documents\Arduino\Forums\roonie\roonie_final\roonie_final.ino:1694:1: warning: control reaches end of non-void function [-Wreturn-type]

 }

 ^
Title: Re: IRremote for my 8x8x8 led cube on the mega
Post by: Roonie on May 03, 2018, 09:54 am
hey,

  Thankx for showing me that I thought that everything was good, since everything seems to work now the way I want. But like I said ` the coding probally isn`t the neatest or effeicent, but hey it gets the job done`.
  I will have a look at it when I`m going to do some upgrades..... I want to display the time and temperature when I press the `info` button on the remote. And also try to build some options in some of the effects.