IRremote for my 8x8x8 led cube on the mega

Hi,

In an other post I got my 8x8x8 led cube working on the Mega.
Now as stated by J-M-L ;

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 ?? :confused:

Ronald

p.s.
I attached the code below as it is too big the post here.

Roon_cube_Mega.ino (23.2 KB)

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

Hello,

Sorry thats all it says exit status 1` error when trying to compile.
When I remove the IRremote.sh libary it compiles just fine....

No, scroll through the output window to see more.

I suspect that you have an interrupt conflict, something with vector 7 ?

You are correct.. I copied the error (using the button in the IDE software) and pasted it below...

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.

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 :wink: Note that guides are for the 328P processor nbut the approach is the same.

E.g. Compilation Error - Programming Questions - Arduino Forum

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

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 cant seem to recieve any ir signals using the serial monitor. Im using a pronto remote with codes that did work with the Uno with the same IR reciever.

On the Mega Im using pin D21 dont know if that also has to be changed in the IRremote libary files ? :confused:

#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

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

z3t0-Arduino-IRremote-2.1.0-96-g2dc97b2.zip (84.7 KB)

Roon_cube_Mega.ino (24 KB)

boarddefs.h (19 KB)

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

//+=============================================================================
// 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.

added the file to the post above ......

Ronald

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.

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 ??

Thats 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?

Roon_cube_Mega.ino (25.2 KB)

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.

/*
  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

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.

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 ........ :slight_smile:

Just a different mind set :wink:

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.

Hi,

I tried replacing the effect_rain code with yours... but no joy :confused:
Trying to compile I got the error;

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 dont yet know how the code works I cant say or see whats wrong.
Big learning curve..... :o

Ronald

Roon_cube_Mega.ino (37.4 KB)

Please post your original version of the effect_rain function. I will compare it with what I presented in reply #11.

Okè thankx,

here is the code so far .....

Ronald

Roon_cube_Mega.ino (39.9 KB)

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.

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" :slight_smile:

PS
Once you start having numbered variables, you should start using arrays.

Hi,

Removed everything from the loop and only pasted in your code. But it wont compile
error message ;

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

Roon_cube_Mega.ino (4.66 KB)

You removed a little bit to much :wink: At least we have something clean to start with 8)

From the code in reply #16

// 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);
    }
  }
}