Loop question - how to wait for input before continuing?

Hello,

I have an IR receiver that receives IR signals. I have various remotes (a Vizio one and a Sony one) that each send different signals (like 12345 is the signal for the "1" button on Vizio, but 1939 is the "1" button on Sony's).

I'm trying to write a program that will store each of these signals in an array. I want to prompt (via Serial monitor) the user to press the "1" button, store that in the array, then prompt the user to press "2", store that, prompt to press "3", store that, etc. for numbers 1 - 9 (and 0) and the remote.

However, I can't seem to figure out how to wait for the code to actually WAIT for the IR to receive a signal, before continuing through the loop. What happens is I get

0.00
Please press button for 0
Please press button for 1
Please press button for 2
Please press button for 3
Please press button for 4
Please press button for 5
Please press button for 6
Please press button for 7
Please press button for 8
Please press button for 9
0.00

It should say "Please press button for 0", then wait until I press that button, store that in the array, then loop and ask for "1", etc.

Here's the code:

#include <IRremote.h>

// IR SENSOR SETUP ------------
const int IRpin = 8;
IRrecv irrecv(IRpin); // create instance of 'irrecv'
decode_results results; //create instance of 'decode_results'
// -------------------------

float btnCodes[9];  // This is the array for the remote's IR code when received by the IR.

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  irrecv.enableIRIn(); // start the receiver
}

void loop() {


  // put your main code here, to run repeatedly:
  for (int i = 0; i <= 9; i++) {
    String x = String(i);
    Serial.print("Please press button for ");
    Serial.println(x);
    if (irrecv.decode(&results)) { // have we rec'd an IR signal?
      Serial.println(results.value);
      btnCodes[i] = Serial.read();
      irrecv.resume(); // Receive the next value
      delay(500);
    }
  }

  Serial.println(btnCodes[1]);
}

At first, I had the code where the string would be btnCodes[i] = results.value (in other words, avoid reading from the Serial monitor for the code, and get it straight from the IR). But, I thought I could have the Serial monitor set the value so the loop would stop. I think what's happening is now, the btnCodes[ i] is being set to literally "Please press button for 0".

Does this make sense? Thanks for any advice!

However, I can't seem to figure out how to wait for the code to actually WAIT for the IR to receive a signal, before continuing through the loop.

You should do nothing in loop() unless there is serial data to read. When there is, you should read it and call a function to get the IR value.

That function should block, using a while(thereIsNoIRData) statement. The while statement should end when there IS an IR value to store, and should return that value.

Forget doing any of this using a for loop.

PaulS:
You should do nothing in loop() unless there is serial data to read. When there is, you should read it and call a function to get the IR value.

That function should block, using a while(thereIsNoIRData) statement. The while statement should end when there IS an IR value to store, and should return that value.

Forget doing any of this using a for loop.

Ahhh, okay - thanks! That makes sense - I will try to work something out and report back with any successes or questions.

edit: argh, I'm stuck. I am having trouble visualizing how to get it started. Looking at Serial Input Basics, I can see how "Receiving several characters from the Serial Monitor" works, but can't figure out how to add the IR remote part. I can't even figure how to say "Please press button 1", then enter data in Serial, then have it loop to "Please press button 2", enter serial data...etc.

:confused:

I can't even figure how to say "Please press button 1", then enter data in Serial, then have it loop to "Please press button 2", enter serial data...etc.

int buttonNumber = 0;

void loop()
{
   Serial.print("Press IR button labeled ");
   Serial.println(buttonNumber);

   int IRVal = GetIRVal();

   // store IRVal in buttonNumber position in some array
   buttonNumber++;
}

Obviously, this needs some kind of if(buttonNumber < n) statement and the code actually shown belongs in the body of the if statement.

Also, the GetIRVal() function needs to be a blocking function that does not return until the value has been received. Finally, the return type of the function, and the variable that the returned value is stored in and the type of the array all need to match.

Lastly, what is the ultimate purpose of this sketch?

The purpose of the sketch is to get the IR data values that the remote's output.

The IR Receiver receives an IR code the remote sends. For the Vizio remote, pressing "1" sends this code, as read by the IR receiver, "20DF8877".

Here's the simple code I use to check if A) the IR receiver is working, B) get the remote's code:

#include <IRremote.h>

int RECV_PIN = 8;
IRrecv irrecv(RECV_PIN);
decode_results results;

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
}

void loop() {
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    irrecv.resume(); // Receive the next value
  }
}

Since remotes has buttons 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, and often others (such as "play", "stop") I want a program that will prompt me (or the user) to press a button on the remote, then have the program store that code (the results.value) in an array.

Ultimately, I will have an array storing the Remote's buttons' codes in an array, then I will be able to use the codes in a project where I control an RGB LED Stip color by pressing "1" for red, "2" for blue, etc. Does that make sense?

And a stretch goal of mine is to use the array, and create a library so I can use the remote codes in various projects without having to enter them first every single time I want to run a program with a remote.

if (irrecv.decode(&results)) {

The irrecv.decode() function returns true or false (there was a value to read, and I read it, or there wasn't a value to read). If it returns true, the value read is stored in the results struct.

You could use a while loop:

while(!irrecv.decode(&results))
{
   // do nothing
}

This loop would end only when a IR button was pressed. When it ends, the function containing this snippet would return results.value.

Oh man, that's awesome :open_mouth: - I haven't used while loops much, but it seems to work excellently. :grinning:

#include <IRremote.h>

int RECV_PIN = 8;
IRrecv irrecv(RECV_PIN);
decode_results results;

long btnCode[9];
int buttonNumber = 0;

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
}

void loop() {
  if (buttonNumber <= 9) {
    Serial.print("Press button labeled ");
    Serial.println(buttonNumber);

    while (!irrecv.decode(&results)) {
      /* DO NOTHING WHEN NO IR SIGNAL IS RECEIVED
       This WHILE loop will run continuously, doing nothing
       until there IS a signal received
      */
    }
    // if IR signals is received, then do this
    getCode();

    buttonNumber++;
  } else {
    for (int i = 0; i <= 9; i++) {
      Serial.print("The remote code for ");
      Serial.print(i);
      Serial.print(" is: ");
      Serial.println(btnCode[i]);
    }
    // The while loop below is to 'stop' the program
    // it will run forever. This prevents you listing all the
    // remote numbers again and again
    while (1) {
    }
  }
}

void getCode() {
  btnCode[buttonNumber] = results.value;
  //    Serial.println(results.value, HEX);
  delay(1000); // Delay, so you don't send 3 signals back to back
  // while the button is depressed.
  irrecv.resume(); // Receive the next value
}
}

That works for what I'm trying to do! Do you see anything in there I could 'tighten up' or any tips?

I'm wonder if "long" is the best way to create the array. In the simple IR example, it returns the results.value as Hex - is there any reason for that, or is it just an option? I use 'long' because I tried int and float and they didn't store properly in the array.

In the simple IR example, it returns the results.value as Hex - is there any reason for that, or is it just an option?

No, it doesn't. It prints the value that was returned in base 16 (HEX). The value is the same whether you print it in base 2 (BIN), base 8 (OCT), base 10 (DEC), or any other base.

I'm wonder if "long" is the best way to create the array.

Yes, it is.

Once the values are all entered and printed, then what? You could have that sketch store the values in EEPROM, so that they could be used by another sketch, without the need to enter them all again.

Hey Paul,

When I don't specify "HEX", "OCT", etc. will the results.value be stored as the RAW data? Does that make sense?

As for storing in EEPROM, I haven't looked in to that before (I've seen that word, but not really looked in to what it is). Is that any different/better than learning to create a library (RFID.h) and then seeing if I can just use a class from that?

When I don't specify "HEX", "OCT", etc. will the results.value be stored as the RAW data?

When you don't specify HEX or OCT where? Those define how the value will be printed, not how it will be stored.