Using functions

I like the idea of using functions they seem to make organizing and understanding code much easier. I want to start using them more.

Here I have a simple sketch to receive IR signals to toggle some LEDs. This first example works as intended but only includes one function toggleLeds();

// the FET Shield uses pin 3 so we lose that functionality on the UNO - Design flaw of the sheild for sure.

#include <IRLib.h>

const byte RECV_PIN = A4; //byte big enough

const byte LedPins[] = {13, 4, 5}; //byte is big enough
bool ledsState = LOW; //bool is big enough

IRrecv My_Receiver(RECV_PIN);
IRdecode My_Decoder;
IRdecodeHash My_Hash_Decoder;

void setup()
{
  //Make all LedPins output
  for (byte i = 0; i < sizeof(LedPins); i++) { //LedPins is a byte so no need to devide the size
    pinMode(LedPins[i], OUTPUT);
  }

  My_Receiver.enableIRIn(); // Start the receiver
  Serial.begin(9600);
  Serial.print("Ready!");
}

void loop() {
  if (My_Receiver.GetResults(&My_Decoder)) {//Puts results in My_Decoder
    My_Hash_Decoder.copyBuf(&My_Decoder);//copy the results to the hash decoder
    My_Decoder.decode();
    Serial.print("real decode type:");
    Serial.print(Pnames(My_Decoder.decode_type));
    Serial.print(" value: 0x");
    Serial.println(My_Decoder.value, HEX);
    My_Hash_Decoder.decode();
    Serial.print("Hash decode: 0x");
    Serial.println(My_Hash_Decoder.hash, HEX); // Do something interesting with this value
    Serial.println("");
    if ((My_Hash_Decoder.hash) == 0x95EB7802) {  // DVD/LD #0
      toggleLeds();
    }
    My_Receiver.resume(); // Turn on the IR receiver for more singnals
  }
}
void toggleLeds() {
  ledsState = !ledsState; //toggle state
  for (byte i = 0; i < sizeof(LedPins); i++) {
    digitalWrite(LedPins[i], ledsState);
    Serial.println("Proof positive, the function is being called");
  }
}

Here is my attempt at putting the IR receiver code into a function. But when I call the function it infinitely toggles the LEDs on and off every half second or so. I'm able to send more IR signals while the toggling is going on but it doesn't do anything. I tried inserting a break; statement in the toggleLeds(); function but that didn't work.

What do I need to do to get the irSignals(); function to work?

#include <IRLib.h>

const byte RECV_PIN = A4; //byte big enough

const byte LedPins[] = {13, 4, 5}; //byte is big enough
bool ledsState = LOW; //bool is big enough

IRrecv My_Receiver(RECV_PIN);
IRdecode My_Decoder;
IRdecodeHash My_Hash_Decoder;

void setup()
{
  //Make all LedPins output
  for(byte i = 0; i < sizeof(LedPins); i++){ //LedPins is a byte so no need to devide the size
    pinMode(LedPins[i], OUTPUT);
  }
  
  My_Receiver.enableIRIn(); // Start the receiver
  Serial.begin(9600);
  Serial.print("Ready!");
}

void loop() {
      irSignals();

    if ((My_Hash_Decoder.hash) == 0x95EB7802) {  // DVD/LD #0
      toggleLeds();
  }
}

void toggleLeds() {
  ledsState = !ledsState; //toggle state
  for(byte i = 0; i < sizeof(LedPins); i++) {
    digitalWrite(LedPins[i], ledsState);
    Serial.println("Proof positive, the function is being called");
}
}

void irSignals() {
  if (My_Receiver.GetResults(&My_Decoder)) {//Puts results in My_Decoder
    My_Hash_Decoder.copyBuf(&My_Decoder);//copy the results to the hash decoder
    My_Decoder.decode();
    Serial.print("real decode type:");
    Serial.print(Pnames(My_Decoder.decode_type));
    Serial.print(" value: 0x");
    Serial.println(My_Decoder.value, HEX);
    My_Hash_Decoder.decode();
    Serial.print("Hash decode: 0x");
    Serial.println(My_Hash_Decoder.hash, HEX); // Do something interesting with this value
    Serial.println("");
    My_Receiver.resume(); // Turn on the IR receiver for more singnals

  }
}

In the working code you are only doing the comparison when GetResults is true, in the non-working code you are always doing it. Try restructuring your function to better match the original code, having it return true only when the comparison succeeds.

boolean irSignals() {

  boolean retVal = false;

  if (My_Receiver.GetResults(&My_Decoder)) {//Puts results in My_Decoder
    My_Hash_Decoder.copyBuf(&My_Decoder);//copy the results to the hash decoder
    My_Decoder.decode();
    Serial.print("real decode type:");
    Serial.print(Pnames(My_Decoder.decode_type));
    Serial.print(" value: 0x");
    Serial.println(My_Decoder.value, HEX);
    My_Hash_Decoder.decode();
    Serial.print("Hash decode: 0x");
    Serial.println(My_Hash_Decoder.hash, HEX); // Do something interesting with this value
    Serial.println("");
    retVal = (My_Hash_Decoder.hash == 0x95EB7802);  // only return true for this value
    My_Receiver.resume(); // Turn on the IR receiver for more singnals
  }

  return(retVal);

}

Then in loop() you would call irSignals() like this

  if (irSignals()) {  // DVD/LD #0
    toggleLeds();
  }

Getting closer. I'm able to get it to compile and upload. It's receiving the signals but not toggling the pins; i.e. it's not calling toggleLeds().

Here's what the code looks like now. How can I get the toggleLeds() function to execute.

#include <IRLib.h>

const byte RECV_PIN = A4; //byte big enough

const byte LedPins[] = {13, 4, 5}; //byte is big enough
bool ledsState = LOW; //bool is big enough

IRrecv My_Receiver(RECV_PIN);
IRdecode My_Decoder;
IRdecodeHash My_Hash_Decoder;

void setup()
{
  //Make all LedPins output
  for (byte i = 0; i < sizeof(LedPins); i++) { //LedPins is a byte so no need to devide the size
    pinMode(LedPins[i], OUTPUT);
  }

  My_Receiver.enableIRIn(); // Start the receiver
  Serial.begin(9600);
  Serial.print("Ready!");
}

void loop() {
  irSignals();

  if ((irSignals()) == 0x95EB7802) {  // DVD/LD #0
    toggleLeds();
  }
}

boolean toggleLeds() {
  ledsState = !ledsState; //toggle state
  for (byte i = 0; i < sizeof(LedPins); i++) {
    digitalWrite(LedPins[i], ledsState);
    Serial.println("Proof positive, the function is being called");
  }
}

boolean irSignals() {

  boolean retVal = false;

  if (My_Receiver.GetResults(&My_Decoder)) {//Puts results in My_Decoder
    My_Hash_Decoder.copyBuf(&My_Decoder);//copy the results to the hash decoder
    My_Decoder.decode();
    Serial.print("real decode type:");
    Serial.print(Pnames(My_Decoder.decode_type));
    Serial.print(" value: 0x");
    Serial.println(My_Decoder.value, HEX);
    My_Hash_Decoder.decode();
    Serial.print("Hash decode: 0x");
    Serial.println(My_Hash_Decoder.hash, HEX); // Do something interesting with this value
    Serial.println("");
    retVal = (My_Hash_Decoder.hash == 0x95EB7802);  // only return true for this value
    My_Receiver.resume(); // Turn on the IR receiver for more singnals
  }

  return (retVal);

}

Now you check for the hash in both the function and in the loop (using the return of the function). But the return is a bool :wink: And to split it up, I don't think you want the hash check inside the function.

Could you try it with loop set to this?

void loop() {

  if( irSignals() ) {  // DVD/LD #0
    toggleLeds();
  } 
}

That should indeed work. But I think now you test it in the wrong place. I think you want to check the hash outside irSignals()

OK, here's where I'm at. I got rid of the test in the function and moved it to the main loop. And I rewrote this line
retVal = (My_Hash_Decoder.hash, HEX); //
But it's still not working

#include <IRLib.h>

const byte RECV_PIN = A4; //byte big enough

const byte LedPins[] = {13, 4, 5}; //byte is big enough
bool ledsState = LOW; //bool is big enough

IRrecv My_Receiver(RECV_PIN);
IRdecode My_Decoder;
IRdecodeHash My_Hash_Decoder;

void setup()
{
  //Make all LedPins output
  for (byte i = 0; i < sizeof(LedPins); i++) { //LedPins is a byte so no need to devide the size
    pinMode(LedPins[i], OUTPUT);
  }

  My_Receiver.enableIRIn(); // Start the receiver
  Serial.begin(9600);
  Serial.print("Ready!");
}

void loop() {
  irSignals();

  if ((irSignals()) == 0x95EB7802)  {  // DVD/LD #0
    toggleLeds();
  }
}

void toggleLeds() {
  ledsState = !ledsState; //toggle state
  for (byte i = 0; i < sizeof(LedPins); i++)
  {
    digitalWrite(LedPins[i], ledsState);
    Serial.println("Proof positive, the function is being called!");
  }
}

boolean irSignals() {

  boolean retVal = false;

  if (My_Receiver.GetResults(&My_Decoder)) {//Puts results in My_Decoder
    My_Hash_Decoder.copyBuf(&My_Decoder);//copy the results to the hash decoder
    My_Decoder.decode();
    Serial.print("real decode type:");
    Serial.print(Pnames(My_Decoder.decode_type));
    Serial.print(" value: 0x");
    Serial.println(My_Decoder.value, HEX);
    My_Hash_Decoder.decode();
    Serial.print("Hash decode: 0x");
    Serial.println(My_Hash_Decoder.hash, HEX); // Do something interesting with this value
    Serial.println("");
    retVal = (My_Hash_Decoder.hash, HEX);  //
    My_Receiver.resume(); // Turn on the IR receiver for more singnals
  }
  return (retVal);
}
if ((irSignals()) == 0x95EB7802)  {  // DVD/LD #0
    toggleLeds();
  }

What do you want irSignals() returns? I think you have two options, let it return it did indeed receive something (that's likely what you planned because you return a bool), or return a received has if it did receive a hash (and it looks like you try to check for that... :wink: )

So better define what a function should do.

ok, I don't think I want the retVal to boolean but rather a HEX, right? So I guess I need to change that variable to handle it. I tried making it a byte but that didn't work.

boolean retVal = false;
to
byte retVal = false;

Still stuck!

#include <IRLib.h>

const byte RECV_PIN = A4; //byte big enough

const byte LedPins[] = {13, 4, 5}; //byte is big enough
bool ledsState = LOW; //bool is big enough

IRrecv My_Receiver(RECV_PIN);
IRdecode My_Decoder;
IRdecodeHash My_Hash_Decoder;

void setup()
{
  //Make all LedPins output
  for (byte i = 0; i < sizeof(LedPins); i++) { //LedPins is a byte so no need to devide the size
    pinMode(LedPins[i], OUTPUT);
  }

  My_Receiver.enableIRIn(); // Start the receiver
  Serial.begin(9600);
  Serial.print("Ready!");
}

void loop() {
  // irSignals();

  if ((irSignals()) == 0x95EB7802)  {  // DVD/LD #0
    toggleLeds();
  }
}

void toggleLeds() {
  ledsState = !ledsState; //toggle state
  for (byte i = 0; i < sizeof(LedPins); i++)
  {
    digitalWrite(LedPins[i], ledsState);
    Serial.println("Proof positive, the function is being called!");
  }
}

boolean irSignals() {

  boolean retVal = false;

  if (My_Receiver.GetResults(&My_Decoder)) {//Puts results in My_Decoder
    My_Hash_Decoder.copyBuf(&My_Decoder);//copy the results to the hash decoder
    My_Decoder.decode();
    Serial.print("real decode type:");
    Serial.print(Pnames(My_Decoder.decode_type));
    Serial.print(" value: 0x");
    Serial.println(My_Decoder.value, HEX);
    My_Hash_Decoder.decode();
    Serial.print("Hash decode: 0x");
    Serial.println(My_Hash_Decoder.hash, HEX); // Do something interesting with this value
    Serial.println("");
    retVal = (My_Hash_Decoder.hash, HEX);  //
    My_Receiver.resume(); // Turn on the IR receiver for more singnals
  }
  return (retVal);
}

richiep:
ok, I don't think I want the retVal to boolean but rather a HEX, right?

Why do you think that? It's your call, both methods work. But you have to expect the same in the function as you do in the loop.

And HEX is just a representation. Like 1 One Uno Eén Ein is just another representation for the same. And a byte can only hold 8-bit. 0 to 255 or in HEX notation 0x00 to 0xFF. The hash is a tiny bit longer :stuck_out_tongue:

Okay, I'm tired and want to go to bed. I'll just post the code and hopefully you can learn from that ::slight_smile:

#include <IRLib.h>

const byte RECV_PIN = A4; //byte big enough

const byte LedPins[] = {13, 4, 5}; //byte is big enough
bool ledsState = LOW; //bool is big enough

IRrecv My_Receiver(RECV_PIN);
IRdecode My_Decoder;
IRdecodeHash My_Hash_Decoder;

void setup()
{
  //Make all LedPins output
  for (byte i = 0; i < sizeof(LedPins); i++) { //LedPins is a byte so no need to devide the size
    pinMode(LedPins[i], OUTPUT);
  }

  My_Receiver.enableIRIn(); // Start the receiver
  Serial.begin(9600);
  Serial.print("Ready!");
}

void loop() {
  // irSignals();

  if (irSignals()){ //Yes, we got a new IR signal, let's see what it is!
    if(My_Hash_Decoder.hash == 0x95EB7802)  {  // DVD/LD #0)
      toggleLeds();
    }
  }
}

void toggleLeds() {
  ledsState = !ledsState; //toggle state
  for (byte i = 0; i < sizeof(LedPins); i++)
  {
    digitalWrite(LedPins[i], ledsState);
    Serial.println("Proof positive, the function is being called!");
  }
}

boolean irSignals() {
  if (My_Receiver.GetResults(&My_Decoder)) {//Puts results in My_Decoder
    My_Hash_Decoder.copyBuf(&My_Decoder);//copy the results to the hash decoder
    My_Decoder.decode();
    Serial.print("real decode type:");
    Serial.print(Pnames(My_Decoder.decode_type));
    Serial.print(" value: 0x");
    Serial.println(My_Decoder.value, HEX);
    My_Hash_Decoder.decode();
    Serial.print("Hash decode: 0x");
    Serial.println(My_Hash_Decoder.hash, HEX); // Do something interesting with this value
    My_Receiver.resume(); // Turn on the IR receiver for more singnals
    return true; //Yes, we had a new IR signal. 
    //WE exit NOW so next return is only executed when the if is not executed
  }
  return false; //No new IR
}

Or:

#include <IRLib.h>

const byte RECV_PIN = A4; //byte big enough

const byte LedPins[] = {13, 4, 5}; //byte is big enough
bool ledsState = LOW; //bool is big enough

IRrecv My_Receiver(RECV_PIN);

void setup()
{
  //Make all LedPins output
  for (byte i = 0; i < sizeof(LedPins); i++) { //LedPins is a byte so no need to devide the size
    pinMode(LedPins[i], OUTPUT);
  }

  My_Receiver.enableIRIn(); // Start the receiver
  Serial.begin(9600);
  Serial.print("Ready!");
}

void loop() {
  // irSignals();

  if(irSignals == 0x95EB7802)  {  //Yes, new hash and it matches!
    toggleLeds();
  }
}

void toggleLeds() {
  ledsState = !ledsState; //toggle state
  for (byte i = 0; i < sizeof(LedPins); i++)
  {
    digitalWrite(LedPins[i], ledsState);
    Serial.println("Proof positive, the function is being called!");
  }
}

//unsinged long to hold the 32-bit ;)
unsigned long irSignals() {
  IRdecode My_Decoder;
  if (My_Receiver.GetResults(&My_Decoder)) {//Puts results in My_Decoder
    //decoders are only needed here
    IRdecodeHash My_Hash_Decoder;
  
    My_Hash_Decoder.copyBuf(&My_Decoder);//copy the results to the hash decoder
    My_Decoder.decode();
    Serial.print("real decode type:");
    Serial.print(Pnames(My_Decoder.decode_type));
    Serial.print(" value: 0x");
    Serial.println(My_Decoder.value, HEX);
    My_Hash_Decoder.decode();
    Serial.print("Hash decode: 0x");
    Serial.println(My_Hash_Decoder.hash, HEX); // Do something interesting with this value
    My_Receiver.resume(); // Turn on the IR receiver for more singnals
    return My_Hash_Decoder.hash; //Yes, new hash is:
    //WE exit NOW so next return is only executed when the if is not executed
  }
  return 0; //No new IR
}

Thanks so much septillion! You've been a huge help these past few days.

I appreciate it very much!

Rich