LED fade will not listen to IR input for interupt.

UKHeliBob:
If I am reading your code right you have

attachInterrupt(pbIn, CheckYellow, HIGH);

pbIn is set to 0 so I interpret that as "call the CheckYellow function when the pin associated with interrupt 0 is HIGH"
Although I freely admit that I am not familiar with interrupts, reading the reference pages I see that interrupt 0 is associated with pin 2 and that the possible values of the third parameter of attachInterrupt() are LOW, CHANGE, RISING OR FALLING.

Have you got anything attached to pin 2 ?
What will happen with the parameter set to HIGH ?

If the interrupt ever causes the CheckYellow function to be called

void CheckYellow() {

if (results.value           == 0x96B47 ) {
    loop();
  }
}



This calls the loop() function. What is that all about ?

Your code won't compile for me because I don't have the library but there are also other errors reported



~~~
sketch_jan16a:69: error: 'IRrecv' does not name a type

sketch_jan16a:70: error: 'decode_results' does not name a type
sketch_jan16a.ino: In function 'void setup()':
sketch_jan16a:76: error: 'irrecv' was not declared in this scope
sketch_jan16a.ino: In function 'void loop()':
sketch_jan16a:80: error: 'irrecv' was not declared in this scope
sketch_jan16a:80: error: 'results' was not declared in this scope
sketch_jan16a.ino: In function 'void CheckYellow()':
sketch_jan16a:184: error: 'results' was not declared in this scope
sketch_jan16a.ino: In function 'void getIR()':
sketch_jan16a:211: error: 'IRrecv' was not declared in this scope
sketch_jan16a:211: error: expected ;' before 'irrecv' sketch_jan16a:212: error: 'decode_results' was not declared in this scope sketch_jan16a:212: error: expected ;' before 'nresults'




Your code has got so mangled through attempts to fix problems that it is practically unreadable. Can I suggest that you create an example of what you want to do, keeping it as simple as possible as I for one cannot see the wood for the trees.

It actually compiles for me with no errors, and it may be because I have extra libraries. Also, I am using compiler version 1.0.1 , not sure if that helps. As far as the interrupt, I have the output pin of the IR receiver going to pin 2, which in a perfect world would register as HIGH the moment I hit a button on the remote. I am trying to keep the interrupt code small, so I wanted it to check and decode looking for only one value, the yellow button.

I tried cleaning the code using some autoit apps I came across, but it keeps stripping out needed operators. I don't have any formal programming training, so this is kind of thrown together by an amateur :wink:

As for the WHILE after the IF statement, the only reason I have that is because it will only execute the pattern once and stop otherwise. When I added WHILE, it actually loops the pattern which is what I was going for.

Even with the IRremote library it will not compile for me. Does the IRremote library depend on others ?

You say that "I have the output pin of the IR receiver going to pin 2" I cannot see where that is defined in your code, nor can I see a pinMode definition for pin 2. Have I missed it ?

Cleaning the code with an an autoit app sounds like a nightmare. Was it written specifically to tidy Arduino code ? What does it try to do ? Putting each brace on its own line would be a start I suppose.

I don't know what you mean about the WHILE after the IF. I was questioning calling loop() from the CheckYellow() function though.

UKHeliBob:
You say that "I have the output pin of the IR receiver going to pin 2" I cannot see where that is defined in your code, nor can I see a pinMode definition for pin 2. Have I missed it ?

I was pulling from http://arduino.cc/en/Reference/AttachInterrupt

If I understand it, int.0 is supposed to point to pin 2 on the Arduino Mega. Essentially, i wanted it to perform this logic:

While in the fade, if you see any change in activity on pin2 which is also connected to the emitter of the IR REC, then determine what code is being sent. If the code is the same as my yellow button, then you can jump out of what you are doing, and go back to the loop.

As for the includes, I will get a list of includes i have on my laptop at home and let you know.

My mental logic which is flawed (because if it wasn't, then this would work) indicated that having an interrupt could call this:

void CheckYellow() {
  if (results.value           == 0x96B47 ) {
    loop();
  }
}

to execute the intended logic above. I'm sure you can see where I am trying to go with it, I just cant fin that little nitch that would actually make it work. Once I get past this hurdle, I can grow the code to all new heights.

The reason the code looks so complicated is i have so many declarations, it looks like they make up half the script. At the moment, there are 2 fade options, one simple, one complex and configurable. It also has a blink what works exactly as designed, because it uses BlinkWithoutDelay with a built in adjustable speed to make it blink faster or slower based on IR volume buttons up and down, which works great.

I took the fader scripts and tried to remove the delay() and substitute it with the BlinkWithoutDelay method which works great, only during the fade calculations, the IR receiver is ignored, and I am thinking this is because it is busy making calculations, or, it does not see enough reason to interrupt the code and take me back to ground zero in the code.

UKHeliBob:
Cleaning the code with an an autoit app sounds like a nightmare. Was it written specifically to tidy Arduino code ? What does it try to do ? Putting each brace on its own line would be a start I suppose.

I intend to rewrite the AutoIT code clean/tidy tools to work with C++, but I really want to tackle this first.

It will be as simple as run the EXE, select your ino or other file, then specify where to save it. It will remove empty lines, give the option to remove comments, and fix all tabs. (and more as the revisions flow)

I think the problem with your understanding of the purpose of an interrupt. You're looking at it like the bell at a speed dating event: once you hear it, you stop talking to the person you are talking to and go talk to someone else. In reality, however, an interrupt is more like a doorbell. If you're making dinner and the doorbell rings, you answer the door then go back to making dinner.

Arrch:
I think the problem with your understanding of the purpose of an interrupt. You're looking at it like the bell at a speed dating event: once you hear it, you stop talking to the person you are talking to and go talk to someone else. In reality, however, an interrupt is more like a doorbell. If you're making dinner and the doorbell rings, you answer the door then go back to making dinner.

Hmm.. Is there a way I can make it more the speed dating type? I was hoping to do this by saying " once the bell rings, see if its yellow, and if it is, stop what you are doing, and call this function"

That is what I hope to do, only because I dont want the code to stop every time it picks up one little Ir blip. Just want it to be able to be interrupted when it sees a certain code come in through IR.

MrKovacic:
Hmm.. Is there a way I can make it more the speed dating type?

Not in a way I care to describe.

What you need to do is restructure the bulk of your code so that it doesn't block, and it doesn't use for loop/delays. You want to be polling for data as often as possible. Here is a simple example demonstrating how to do that using a simple LED fade in which the fade up/fade down is determined by the state of a switch.

The first example will not allow you to "interrupt" the fading; you have to let the cycle finish before you can change direction:

const int ledPin = 13;
const int switchPin = 2;
const unsigned long fadeInterval = 20;

void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(ledPin, INPUT_PULLUP);
}

void loop()
{
  int switchState = digitalRead(switchPin);
  for (int i=0; i<=255; i++)
  {
    if (switchState == HIGH)
      analogWrite(ledPin, i);
    else
      analogWrite(ledPin, 255-i);

    delay(fadeInterval);
  }
}

To allow it to respond more quickly to the switch, you can rewrite it like this:

const int ledPin = 13;
const int switchPin = 2;
const unsigned long fadeInterval = 20;

unsigned long lastFadeTime = 0;
int pwmValue = 0;

void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(ledPin, INPUT_PULLUP);
}

void loop()
{
  int switchState = digitalRead(switchPin);
  if (millis() - lastFadeTime > fadeInterval)
  {
    lastFadeTime = millis();
    if (switchState == HIGH)
      pwmValue = constrain(pwmValue+1, 0, 255);
    else
      pwmValue = constrain(pwmValue-1, 0, 255);

    analogWrite(ledPin, pwmValue);
  }
}

The latter sketch allows us to poll the switch's state much more often than the former sketch.

*Disclaimer: I didn't compile or test these sketches

Arrch:

MrKovacic:
Hmm.. Is there a way I can make it more the speed dating type?

Not in a way I care to describe.

What you need to do is restructure the bulk of your code so that it doesn't block, and it doesn't use for loop/delays. You want to be polling for data as often as possible. Here is a simple example demonstrating how to do that using a simple LED fade in which the fade up/fade down is determined by the state of a switch.

The first example will not allow you to "interrupt" the fading; you have to let the cycle finish before you can change direction:

const int ledPin = 13;

const int switchPin = 2;
const unsigned long fadeInterval = 20;

void setup()
{
 pinMode(ledPin, OUTPUT);
 pinMode(ledPin, INPUT_PULLUP);
}

void loop()
{
 int switchState = digitalRead(switchPin);
 for (int i=0; i<=255; i++)
 {
   if (switchState == HIGH)
     analogWrite(ledPin, i);
   else
     analogWrite(ledPin, 255-i);

delay(fadeInterval);
 }
}




To allow it to respond more quickly to the switch, you can rewrite it like this:



const int ledPin = 13;
const int switchPin = 2;
const unsigned long fadeInterval = 20;

unsigned long lastFadeTime = 0;
int pwmValue = 0;

void setup()
{
 pinMode(ledPin, OUTPUT);
 pinMode(ledPin, INPUT_PULLUP);
}

void loop()
{
 int switchState = digitalRead(switchPin);
 if (millis() - lastFadeTime > fadeInterval)
 {
   lastFadeTime = millis();
   if (switchState == HIGH)
     pwmValue = constrain(pwmValue+1, 0, 255);
   else
     pwmValue = constrain(pwmValue-1, 0, 255);

analogWrite(ledPin, pwmValue);
 }
}




The latter sketch allows us to poll the switch's state much more often than the former sketch.

*Disclaimer: I didn't compile or test these sketches

That is a good explanation, however I am able to have it change speeds, and the switching mechanism according to your code is a physical switch, where I use Infrared.

The goal I am looking to accomplish is, if the IR receiver picks up the code: 0x96B47, it simply resets. That is the simplest form I can put it in, because on reset, there is no longer a previous value to determine what the script should be doing.

Is that possible?

If IR sees 0x96B47, then reset the arduino. While waiting for that code, let the fades work.

MrKovacic:
however I am able to have it change speeds, and the switching mechanism according to your code is a physical switch, where I use Infrared.

Which is why I called it a "simple example" and not "the code to fix your problem". It was simply demonstrate the concept and rewriting code that utilizes methods which cause a delayed response.

The goal I am looking to accomplish is, if the IR receiver picks up the code: 0x96B47, it simply resets. That is the simplest form I can put it in, because on reset, there is no longer a previous value to determine what the script should be doing.

So you need a state machine. Whenever you receive the "reset" code you set it back to it's original state. It still requires ensuring the concept demonstrated in my last post, except instead of polling a switch, you will be checking the state.

Arrch:

MrKovacic:
however I am able to have it change speeds, and the switching mechanism according to your code is a physical switch, where I use Infrared.

Which is why I called it a "simple example" and not "the code to fix your problem". It was simply demonstrate the concept and rewriting code that utilizes methods which cause a delayed response.

The goal I am looking to accomplish is, if the IR receiver picks up the code: 0x96B47, it simply resets. That is the simplest form I can put it in, because on reset, there is no longer a previous value to determine what the script should be doing.

So you need a state machine. Whenever you receive the "reset" code you set it back to it's original state. It still requires ensuring the concept demonstrated in my last post, except instead of polling a switch, you will be checking the state.

Yes and no... It would have to look for not only pin 2 to go HIGH, but to see if it brings in a certain value, and if it does, rerun the loop, or reset.. whatever is easier to call.

In the example,

   if (switchState == HIGH)

would execute the moment any IR signal is picked up.

MrKovacic:
Yes and no... It would have to look for not only pin 2 to go HIGH, but to see if it brings in a certain value, and if it does, rerun the loop, or reset.. whatever is easier to call.

Neither, you would check the conditions and update the state variable; you can't "rerun" the loop or reset the device.

In the example,

   if (switchState == HIGH)

would execute the moment any IR signal is picked up.

Again, it was a simple example to demonstrate the concept of not "pausing code" to allow other code to run frequently; you seem to be focusing on the conditions which were just part of making the example simple, and completely missing the point of the example.

Arrch:

MrKovacic:
Yes and no... It would have to look for not only pin 2 to go HIGH, but to see if it brings in a certain value, and if it does, rerun the loop, or reset.. whatever is easier to call.

Neither, you would check the conditions and update the state variable; you can't "rerun" the loop or reset the device.

In the example,

   if (switchState == HIGH)

would execute the moment any IR signal is picked up.

Again, it was a simple example to demonstrate the concept of not "pausing code" to allow other code to run frequently; you seem to be focusing on the conditions which were just part of making the example simple, and completely missing the point of the example.

I understand the theory of having the code check something while it is in the process of a fade, what I am stuck on is actually getting it to work. In theory, it should be polling the IR pin to see if there is any incoming signals and check to see if its the yellow button. If it is the yellow button, the value of "results.value" should change, and it would execute whatever is in the new value. With the code the way it is, it should work, but for some strange reason it doesn't.

So then post "the code the way it is"

MrKovacic:
I'll start by saying this, im pretty good with Autoit, but a baby when it comes to C++..

I have a decent script set up to blink LED's using an old blu-ray player remote. As it stands, the remote has numbered buttons, volume buttons etc.. It also has a red, green, blue and yellow button. I have it so if I push the R, G or B button, the LED of that color lights up. If I push Yellow, it shuts everything off. I am trying to incorperate fading into this, and while it will being and run the fade, it will no longer pay attention to the IR remote during the fade. I tried removing all delays, and even adding in some calls to read the IR, but no matter what I do, the Fade codes stay going until I reset the Arduino.

I have a simple blink on button 2, a fairly simple fade using cos on button 1, and a more advanced fade on button 7.

While any of the fades are going, I can't get Arduino to check the IR for changes.

here is the code:

// include some junk

#include <IRremote.h>

int RECV_PIN = 11;
int periode = 2000;
int displace = 500;
int testtime = 1000;
long time=0;
/*  FUTURE USE
int RED1 = 2;
int GREEN1 = 3;
int BLUE1 = 4;

int RED2 = 5;
int GREEN2 = 6;
int BLUE2 = 7;

int RED3 = 8;
int GREEN3 = 9;
int BLUE3 = 10;

int RED4 = 11;
int GREEN4 = 12;
int BLUE4 = 13;
*/
int redPin = 7;   // Red LED,   connected to digital pin 9
int grnPin = 6;  // Green LED, connected to digital pin 10
int bluPin = 8;  // Blue LED,  connected to digital pin 11

int value, value2, value3 ;

int RED = 7;
int GREEN = 6;
int BLUE = 8;

// Color arrays
int black[3]  = { 0, 0, 0 };
int white[3]  = { 100, 100, 100 };
int red[3]    = { 100, 0, 0 };
int green[3]  = { 0, 100, 0 };
int blue[3]   = { 0, 0, 100 };
int yellow[3] = { 100, 100, 0 };
int pink[3] = { 0, 100, 100 };
int magenta[3] = { 100, 0, 100 };

// etc.

// Set initial color
int redVal = black[0];
int grnVal = black[1];
int bluVal = black[2];

//int wait = 2;      // no longer used

int prevR = redVal;
int prevG = grnVal;
int prevB = bluVal;
IRrecv irrecv(RECV_PIN);
decode_results results;
long previousMillis = 0;   
long interval = 1000;
long chill = 2;

int ledState = LOW; // only for BLUE LED for now, will add more later, just want to blink blue for now
int blinkone = 0;
int blinktwo= 0;
int blinkthree = 0;
int blinkfour = 0;
int blinkfive = 0;
int blinksix = 0;
int blinkseven = 0;
int blinkeight = 0;
int blinknine = 0;

void setup() //Just some obvious crap
{
  pinMode(8, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(6, OUTPUT);
  irrecv.enableIRIn(); // kick on the IR receiver
}

void loop() {
  unsigned long currentMillis = millis(); // Start the arduino counting so it can keep time
  if (irrecv.decode(&results)) {
    if (results.value == 0x66B47) { // BLUE button on the remote
      digitalWrite(BLUE, HIGH);
    }
    else if (results.value == 0xE6B47) { // RED button on the remote
      digitalWrite(RED, HIGH);
    }   
   
        else if (results.value == 0x490) { // Vol Up button on the remote
      interval = interval - 50;
      if  (interval < 75) {
            interval =100;
                           }
    } 
   
        else if (results.value == 0xC90) { // Vol Down button on the remote
            interval = interval + 50;
    } 
   
            else if (results.value == 0x290) { // Vol Down button on the remote
            interval = 1000;
    } 
   
        else if (results.value == 0x16B47) { // GREEN button on the remote
      digitalWrite(GREEN, HIGH);
    }
   
        else if (results.value == 0xB47) { // 1 button on the remote
  while (results.value == 0xB47) {
  time = millis();
  value = 128+127cos(2PI/periodetime);
  value2 = 128+127
cos(2PI/periode(displace-time));
  value3 = 128+127cos(2PI/periode*(testtime-time));
  analogWrite(redPin, value);           // sets the value (range from 0 to 255)
  analogWrite(grnPin, value2);           // sets the value (range from 0 to 255)
  analogWrite(bluPin, value3);
  irrecv.resume();
        }}
       
       
        else if (results.value == 0x80B47) { // 2 button on the remote

blinkone = 1;
blinktwo= 0;
blinkthree = 0;
blinkfour = 0;
blinkfive = 0;
blinksix = 0;
blinkseven = 0;
blinkeight = 0;
blinknine = 0;
        }        else if (results.value == 0x40B47) { // 3 button on the remote

blinkone = 0;
blinktwo= 0;
blinkthree = 1;
blinkfour = 0;
blinkfive = 0;
blinksix = 0;
blinkseven = 0;
blinkeight = 0;
blinknine = 0;
        }        else if (results.value == 0xC0B47) { // 4 button on the remote

blinkone = 0;
blinktwo= 0;
blinkthree = 0;
blinkfour = 1;
blinkfive = 0;
blinksix = 0;
blinkseven = 0;
blinkeight = 0;
blinknine = 0;
        }        else if (results.value == 0x20B47) { // 5 button on the remote

blinkone = 0;
blinktwo= 0;
blinkthree = 0;
blinkfour = 0;
blinkfive = 1;
blinksix = 0;
blinkseven = 0;
blinkeight = 0;
blinknine = 0;
        }        else if (results.value == 0xA0B47) { // 6 button on the remote

blinkone = 0;
blinktwo= 0;
blinkthree = 0;
blinkfour = 0;
blinkfive = 0;
blinksix = 1;
blinkseven = 0;
blinkeight = 0;
blinknine = 0;
        }        else if (results.value == 0x60B47) { // 7 button on the remote
while (results.value == 0x60B47) {

crossFade(red);
  crossFade(green);
  crossFade(blue);
  crossFade(yellow);
  crossFade(white);
  crossFade(pink);
  crossFade(magenta);
  }

}        else if (results.value == 0xE0B47) { // 8 button on the remote

blinkone = 0;
blinktwo= 0;
blinkthree = 0;
blinkfour = 0;
blinkfive = 0;
blinksix = 0;
blinkseven = 0;
blinkeight = 1;
blinknine = 0;
        }        else if (results.value == 0x10B47) { // 9 button on the remote

blinkone = 0;
blinktwo= 0;
blinkthree = 0;
blinkfour = 0;
blinkfive = 0;
blinksix = 0;
blinkseven = 0;
blinkeight = 0;
blinknine = 1;
        }

else if (results.value == 0x96B47  ) { // YELLOW - shut everything off. aka blackout
      digitalWrite(BLUE, LOW);
      digitalWrite(RED, LOW);
      digitalWrite(GREEN, LOW);
      blinkone = 0; // stops that pesky blue light from blinking like a little bitch

}
    irrecv.resume(); //doesnt matter where you put this, it workd right here so I guess dont mess with it
  }
 
 
 
  if (blinkone == 1) {   // First flash pattern. On and off, bow to its awesomeness!
     
  if(currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;   
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

digitalWrite(BLUE, ledState);
      }   
     }   //include this
 
}

int calculateStep(int prevValue, int endValue) {
  int step = endValue - prevValue; // What's the overall gap?
  if (step) {                      // If its non-zero,
    step = 1020/step;              //   divide by 1020
  }
  return step;
}

int calculateVal(int step, int val, int i) {

if ((step) && i % step == 0) { // If step is non-zero and its time to change a value,
    if (step > 0) {              //   increment the value if step is positive...
      val += 1;           
    }
    else if (step < 0) {         //   ...or decrement it if step is negative
      val -= 1;
    }
  }
  // Defensive driving: make sure val stays in the range 0-255
  if (val > 255) {
    val = 255;
  }
  else if (val < 0) {
    val = 0;
  }
  return val;
}

void crossFade(int color[3]) {
    unsigned long currentMillis = millis();
  // Convert to 0-255
  int R = (color[0] * 255) / 100;
  int G = (color[1] * 255) / 100;
  int B = (color[2] * 255) / 100;

int stepR = calculateStep(prevR, R);
  int stepG = calculateStep(prevG, G);
  int stepB = calculateStep(prevB, B);

for (int i = 0; i <= 1020; i++) {
    redVal = calculateVal(stepR, redVal, i);
    grnVal = calculateVal(stepG, grnVal, i);
    bluVal = calculateVal(stepB, bluVal, i);

analogWrite(redPin, redVal);   // Write current values to LED pins
    analogWrite(grnPin, grnVal);     
    analogWrite(bluPin, bluVal);
   
int zag = 1;
do {
zag = zag + 1;
getIR();
} while (zag < 200);

}
  // Update current values for next loop
  prevR = redVal;
  prevG = grnVal;
  prevB = bluVal;

}

void getIR() {
IRrecv irrecv(RECV_PIN);
decode_results nresults;
}




Any help would be very appreciated! :astonished:
void getIR() {
IRrecv irrecv(RECV_PIN);
decode_results nresults;
}

I assume this is what you think is checking for IR commands while you are fading? It's not, it's declaring two local variables, then destroying them. This goes back to the very first response in this thread made by Nick.

My initial reason for posting was to try to get some help and or direction on how to handle that, in a matter I might understand. I did mention that I am new to this, and most of what I am being told is that my code is all over the place and hard to read, and that most of it does nothing. You assume correct, I was hoping that would read the IR and process as needed. I can already see what not to do, because the code doesn't work as I had hoped. After spending days and weeks doing what not to do, and googling for answers and hitting the code reference libraries, I will eventually come up with the answer. I was hoping to shorten that time by seeking help here.

Also, here are the libraries I have installed:

EEPROM
Ethernet
Firmata
IRremote
LiquidCrystal
SD
Servo
SoftwareSerial
SPI
Stepper
Wire

Without re-reading all 4 pages of this thread, this is what I recall...

You wanted to break out of a loop when an IR code was received. The loop was fading something.

This is eminently achievable, I think. However your original code had two problems:

  • Your function getIR, which you call repeatedly, does nothing useful, because it does not alter any global variables.
  • Even if it did set global variables, you are not testing any variables in the loop which does the fade.

I can't see that you have attempted to address those issues.

Interesting. I took the fader out of the main IF section of the statements, and put it after in its own section, still under loop, and now it seems to be working.

I will say this, I don't quite understand it, but I will go with it.

Thanks!