Infrared signal send massive delay

Dear all,

I am trying to send a number via infrared to another arduino - this is suppossed to work back and forth.
Upon pressing of a button you send the number/light a LED and the other one should receive and display this number in the serial monitor as well as lighting a LED.
Problem:
When using the functions (sendIR, receiveIR) together there always is the problem that the button connected only reacts after a couple of seconds, however if using only the sendIR function it works as planned and sends the number. I also tried only receiving the data and that also worked but as soon as both functions are enabled it stalls. Can anyone point me to where the error might be?
Thanks so much in advance and sorry for the inconvenience :confused:

int sensorPin  = 2;      // Sensor pin 3
int senderPin  = A2;      // Infrared LED on Pin A2
int triggerPin = 4;      // Pushbutton Trigger on Pin 4
int speakerPin = 12;     // Positive Lead on the Piezo
int blinkPin   = 13;     // Positive Leg of the LED we will use to indicate signal is received
int reloadPin  = 11;     // pushbutton for reload connected to Pin 11
int startBit   = 800;   // This pulse sets the threshold for a transmission start bit
int endBit     = 1000;   // This pulse sets the threshold for a transmission end bit
int redPin     = 6;
int grnPin     = 5;
int one        = 400;   // This pulse sets the threshold for a transmission that represents a 1
int zero       = 200;    // This pulse sets the threshold for a transmission that represents a 0
int trigger;             // This is used to hold the value of the trigger read;
int reload;              // used to hold the value of the reload button state
boolean reloaded = false; // boolean used to remember if the reload button has been pressed
boolean fired  = 0;  // Boolean used to remember if the trigger has already been read.
int ret[2];              // Used to hold results from IR sensing.
int waitTime = 300;     // The amount of time to wait between pulses
int reloadTime = 2000;

int myID     = 67;      // This is your unique player code;
int myTeam = 3;        // you are in this team
int HEALED = 0;
int maxShots   = 30;      // You can fire 30 shots;
int maxHits    = 10;      // After 10 hits you are dead;
int myShots    = 0;      // amount of shots fired
int myHits     = 0;      // hits taken already
int fullauto   = 0;      // if true full automatic firing mode is activated



void setup() {
  pinMode(blinkPin, OUTPUT);
  pinMode(speakerPin, OUTPUT);
  pinMode(senderPin, OUTPUT);
  pinMode(triggerPin, INPUT);
  pinMode(sensorPin, INPUT);
  pinMode(reloadPin, INPUT);
  randomSeed(analogRead(0));
  for (int i = 1;i < 4;i++) {
    digitalWrite(blinkPin, HIGH);
    playTone(900*i, 200);
    digitalWrite(blinkPin, LOW);
    delay(200);
  }

  Serial.begin(9600);
  Serial.println("Ready: ");  
}

void loop() {
 

 senseFire();
 senseIR();

}
int convert(int bits[], int x) {
  int result = 0;
  int seed   = 1;
  for(int i=x;i>=0;i--) {
    if(bits[i] == 1) {
      result += seed;
    }
    seed = seed * 2;
  }
  return result;
}

void senseFire() {
  trigger = digitalRead(triggerPin);
  if (fullauto == true) { // full automatic weapon mode enabled? 
  fired = false; }
  if (trigger == LOW && fired == false) {
    Serial.println("Button Pressed");
    fired = true;
    myShots++;
    if (myHits >= maxHits) {
      Serial.println("GAME OVER");
      Destruct();
    } else if (myHits <= maxHits && myShots <= maxShots) {
      Serial.print("Firing Shot : ");
      Serial.println(myShots);
      Serial.println(myID);
      fireShot(myID);
    }
    else if (myShots > maxShots) {
      Serial.println("out of ammo. - RELOAD");  
    }
    } else if (trigger == HIGH) {
    if (fired == true) {
      Serial.println("Button Released");
    }
    // reset the fired variable
    fired = false;
  }
}



void fireShot(int player) {
  int encoded[8];
  digitalWrite(blinkPin, HIGH);
  for (int i=0; i<8; i++) {
    encoded[i] = player>>i & B1;   //encode data as '1' or '0'
    Serial.print(i);
    Serial.print(":");
    Serial.println(encoded[i]);
    
  }
 
  // send startbit
  oscillationWrite(senderPin, startBit);
  // send separation bit
  digitalWrite(senderPin, HIGH);
  delayMicroseconds(waitTime);
  // send the whole string of data
  for (int i=7; i>=0; i--) {
    if (encoded[i] == 0) {
      oscillationWrite(senderPin, zero);
    } else {
      oscillationWrite(senderPin, one);
    }
    // send separation bit
    digitalWrite(senderPin, HIGH);

    delayMicroseconds(waitTime);
       
  }
  oscillationWrite(senderPin, endBit);
  playTone(100, 5);
  digitalWrite(blinkPin, LOW);
}

void oscillationWrite(int pin, int time) {
  for(int i = 0; i <= time/26; i++) {
    digitalWrite(pin, HIGH);
    delayMicroseconds(13);
    digitalWrite(pin, LOW);
    delayMicroseconds(13);
  }
}

void senseIR() {
  int who[8];
  while(pulseIn(sensorPin, LOW, 50) < startBit) {
    digitalWrite(blinkPin, LOW);
    ret[0] = -1;
  }
  digitalWrite(blinkPin, HIGH);
  who[0]   = pulseIn(sensorPin, LOW);
  who[1]   = pulseIn(sensorPin, LOW);
  who[2]   = pulseIn(sensorPin, LOW);
  who[3]   = pulseIn(sensorPin, LOW);
  who[4]  = pulseIn(sensorPin, LOW);
  who[5]  = pulseIn(sensorPin, LOW);
  who[6] = pulseIn(sensorPin, LOW);
  who[7] = pulseIn(sensorPin, LOW);

  Serial.println("---who---");
  for(int i=0;i<=7;i++) {
    Serial.print(i);
    Serial.print(":");
    Serial.println(who[i]);
    if(who[i] > one) {
      who[i] = 1;
    } else if (who[i] > zero) {
      who[i] = 0;
    } else {
      // Since the data is neither zero or one, we have an error
      Serial.println("unknown player");
      ret[0] = -1;
      return;
    }
  }
  ret[0]=convert(who, 7);
  Serial.println(ret[0]);
  
}

Credit for parts of the code goes to Duane O’Brien.

It looks like your senseIR() function will not return untill a byte has been read, What happens if nothing is being recieved?

if I understood the syntax of pulseIn correctly, then it should give a ret[0]=-1 when nothing is measured or at least nothing longer than the startBit, correct? At least that was what I intended to do there :slight_smile:

while(pulseIn(sensorPin, LOW, 50) < startBit) {
    digitalWrite(blinkPin, LOW);
    ret[0] = -1;

PulseIn documentation

For example, if value is HIGH, pulseIn() waits for the pin to go HIGH, starts timing, then waits for the pin to go LOW

Ok, let me try to underrstand this:

The function waits for the pin to be low -> receiving a signal
If this never happens, the function tries to wait until it happens, which is why the process does not work and is so slow?
So I just need to add something like an automatic return (like -1) of the function unless something is measured? - would that mean that my pulseIn function would be high, since no signal is detected, or would it be smarter to use IF / ELSE and not WHILE?

lefthand3r:
Ok, let me try to underrstand this:

The function waits for the pin to be low -> receiving a signal
If this never happens, the function tries to wait until it happens, which is why the process does not work and is so slow?

I think you're getting there. I suspect the best option of all would be to ditch pulseIn when looking for the start bit. I'm not familiar enough with IR to be more specific. But basically you want to have a quick look at the line. If nothings happening then return immediately. IF the start is detected, then perhaps you could use pulseIn to shift in the other bits.

Why not use IRLib or IRremote libraries.

You can send and/or receive 32 bit values using the NEC protocol and all the messy stuff is handled in the library!

simple as ..... irsend.sendNEC(0xF1F2F3F4,32);

Reception will also happen for you (non-blocking). First step is to try out hte examples provided with the libraries.