My code is making my IR sensor response time too slow

Hi guys,

I am working in a project for my foosball table. The idea is to play some random audios during the playgame. Then, once an IR sensor is broken (a goal has been scored) the ongoing audio stops and is followed by the trigger of another audio ("goal") and the score is changed on my 7-segment LED. It seems simple, but it is a lot for a newbie as myself. After racking my brain for a while to make the project works (which does now), I am experiencing a very annoying issue: The reaction time of my IR sensor (Adrafuit 3mm LED) is too slow so it never triggers the device. The problem here is that these sensors are really fast and I don't think they are the origin of my problem. In fact, if I test it in a simple sketch, it works just fine. Therefore, I think there is something on my code that is making it act to slow. Is that possible? I am sharing the code below so you guys can give me some feedback. I am sure it has a lot of junk.
Thanks a lot for the help

/* 
  Code adapted from Morgenthaler and Leo at Swiss school www.oszt.ch by Daniel da Silva
*/
                                           
// 3 lines importing libraries for the Adafruit display 
#include <Wire.h>                                 
#include <Adafruit_GFX.h>                         
#include "Adafruit_LEDBackpack.h"
#include <Adafruit_Soundboard.h>
#include "SoftwareSerial.h"

long randNumber;
long randGol;
int announcer = 0;

// Initailizing the 7-segment display 
Adafruit_7segment matrix = Adafruit_7segment();   

// Defining varialbes for the two goals
int Rot;                                          
int Blau;
int a = 0;
int b = 0;

// Defining Arduino's board-LED. For controlling purpose only during coding
#define LEDPIN 13                                 
                                                 
// Defining the two pins the data connections of the breakbeam sensors 
#define SENSORPIN 4                               
#define SENSORPIN2 2  

// Defining the pin for the back to zero button                            
#define SENSORPIN3 7   

#define SFX_TX 3
#define SFX_RX 6
// Connect to the RST pin on the Sound Board
#define SFX_RST 10

// we'll be using software serial
SoftwareSerial ss = SoftwareSerial(SFX_TX, SFX_RX);
// pass the software serial to Adafruit_soundboard, the second
// argument is the debug port (not used really) and the third 
// arg is the reset pin
Adafruit_Soundboard sfx = Adafruit_Soundboard(&ss, NULL, SFX_RST);
// can also try hardware serial with
// Adafruit_Soundboard sfx = Adafruit_Soundboard(&Serial1, NULL, SFX_RST);

 // Initalizing and defining states for the breakbeam sensors and the back to zero button 
int sensorState = 0, lastState=0;               
int sensorState2 = 0, lastState2=0;              
int sensorState3 = 0, lastState3=0;              

char *soundName[] = {
  
  "01      OGG",
  "02      OGG",
  "03      OGG",
  "04      OGG",
  "05      OGG",
  "06      OGG",
  "07      OGG",
  "08      OGG",
  "09      OGG",
  "10      OGG"
  "11      OGG",
  "12      OGG",
  "13      OGG",
  "14      OGG",
  "15      OGG",
  "16      OGG"
  "17      OGG",
  "18      OGG",
  "19      OGG",
  "20      OGG",
  "21      OGG",
  "22      OGG",
  "23      OGG",
  "24      OGG",
  "25      OGG",
  "26      OGG",
  "27      OGG",
  "24      OGG",
  "25      OGG",
  "26      OGG",
  "27      OGG",
  "28      OGG"
};

char *gol[] = {
  
"1004    OGG",
"1003    OGG"
  
    };

                                                 
void setup() {   

announcer = 0;
       Serial.begin(9600);

     
  // Initializing Arduino's board LED for output                                                
  pinMode(LEDPIN, OUTPUT);                        
                                                  
  // Initializing pin for input from breakbeam sensor                                               
  pinMode(SENSORPIN, INPUT);  
  // Activating the pullup resistor for this pin to make the two sensor states clear for Arduino                    
  digitalWrite(SENSORPIN, HIGH);                  

  // Same for other breakbeam sensor
  pinMode(SENSORPIN2, INPUT);                     
  digitalWrite(SENSORPIN2, HIGH);

  // Same for back to zero button
  pinMode(SENSORPIN3, INPUT);                     
  digitalWrite(SENSORPIN3, HIGH);

  // Start value for goals
  Rot = 0;                                         
  Blau = 0;

  //Define address for display
  matrix.begin(0x70);         

                       ss.begin(9600);
                       randomSeed(analogRead(0));
                       
}



void loop(){

a = Rot - Blau; 
b = Blau - Rot; 

    
  // Next 3 lines: Read and save states of the 2 sensors and the back to zero button                                               
  sensorState = digitalRead(SENSORPIN);           
  sensorState2 = digitalRead(SENSORPIN2);
  sensorState3 = digitalRead(SENSORPIN3);  

// The following lines are for displaying the the goal values on the display.
  // This if argument prevents from displaying a zero with numbers under 10
  if(Rot / 10)
  // Display position 0 will show the first position of goal variable Rot
  matrix.writeDigitNum(0, (Rot / 10) );    
    // Display position 1 will show the second position of goal variable Rot      
    matrix.writeDigitNum(1, Rot % 10 );
    // A colon will be displayed between the two varialbes            
    matrix.drawColon(true);  
    
 // This if argument prevents from displaying a zero for other variable 
  if(Blau / 10)
    // Display position 3 will show the first position of goal variable Blau                     
    matrix.writeDigitNum(3, (Blau / 10) );   


    //  Display position 4 will show the second position of goal variable Blau     
    matrix.writeDigitNum(4, Blau % 10 );    
    // Display everyting above      
    matrix.writeDisplay();         

switch (announcer) {
    
    case 0:
    Serial.println("Start");//print the number
    sfx.playTrack("1002    OGG");    
    announcer = 1;
    break;
    
    case 1:

    if (sensorState == HIGH || sensorState2 == HIGH) { 
    randNumber = random(0, 30);
    Serial.println(randNumber);//print the number
    sfx.playTrack(soundName[randNumber]);
    
     
      }
      if (Rot == 10 || Blau == 10) announcer = 6;
      if (sensorState == LOW && a <=2) announcer = 2;
      if (sensorState2 == LOW && b <=2) announcer = 3;
      if (sensorState == LOW && a >=3) announcer = 4;
      if (sensorState2 == LOW && b >=3) announcer = 5;
           
      break;

    case 2:
      
      Serial.println("Gol team 1");//print the number
      sfx.stop();
      randGol = random(0, 4);
      Serial.println(randGol);//print the number
      Rot = Rot + 1;      
      sfx.playTrack(gol[randGol]);
      
      announcer = 1;
      break;

    case 3:
      
     Serial.println("Gol team 2");//print the number
      sfx.stop();
      Blau = Blau + 1;         
      sfx.playTrack("1001    OGG");

      announcer = 1;
      
      break;

 case 4:
      
      Serial.println("Gol team 1");//print the number
      sfx.stop();

      Serial.println("Hammering");//print the number
      Rot = Rot + 1;      
      sfx.playTrack("1005    OGG");
      
      announcer = 1;
      break;

 case 5:
      
     Serial.println("Gol team 2");//print the number
      sfx.stop();
      Blau = Blau + 1;     
      Serial.println("Hammering");//print the number    
      sfx.playTrack("1005    OGG");
    
      announcer = 1;
      break;

      case 6:
      
     Serial.println("Finish");//print the number
      sfx.stop();   
      sfx.playTrack("1006    OGG");
      a = Rot - Blau; 
      b = Blau - Rot; 
      matrix.clear();
      announcer = 0;
      break;
        
}


     // Check status of back to zero button 
  if (sensorState3 && !lastState3) {               
  }
  // If pressed, the serial display would show "reset" and both goal variables are reset to zero.
  if (!sensorState3 && lastState3) {
    Serial.println("reset");                       
    Blau = 0;                                      
    Rot = 0;
    // Clears everything displayed on LED
    matrix.clear();
  }
 // Save the last sensor states 
  lastState = sensorState;                     
  lastState2 = sensorState2;                       
  lastState3 = sensorState3;
}

It seems simple, but it is a lot for a newbie as myself.

Got stuff for a newbie !!

these sensors are really fast and I don't think they are the origin of my problem. In fact, if I test it in a simple sketch, it works just fine.

Yep i agree, You are doing quite a lot of stuff in between polling the sensor pin. I removed some comments from your code to see what is actually going on. Is that sfx.playTrack(" ") happening in the background or in a blocking way ? does the reset button work while it is playing something ?

/*
  Code adapted from Morgenthaler and Leo at Swiss school www.oszt.ch by Daniel da Silva
*/

// 3 lines importing libraries for the Adafruit display
#include <Wire.h>
#include <Adafruit_GFX.h>
#include "Adafruit_LEDBackpack.h"
#include <Adafruit_Soundboard.h>
#include "SoftwareSerial.h"

long randNumber;
long randGol;
int announcer = 0;

// Initailizing the 7-segment display
Adafruit_7segment matrix = Adafruit_7segment();

// Defining varialbes for the two goals
int Rot;
int Blau;
int a = 0;
int b = 0;

// Defining Arduino's board-LED. For controlling purpose only during coding
#define LEDPIN 13

// Defining the two pins the data connections of the breakbeam sensors
#define SENSORPIN 4
#define SENSORPIN2 2

// Defining the pin for the back to zero button
#define SENSORPIN3 7

#define SFX_TX 3
#define SFX_RX 6
// Connect to the RST pin on the Sound Board
#define SFX_RST 10

// we'll be using software serial
SoftwareSerial ss = SoftwareSerial(SFX_TX, SFX_RX);
// pass the software serial to Adafruit_soundboard, the second
// argument is the debug port (not used really) and the third
// arg is the reset pin
Adafruit_Soundboard sfx = Adafruit_Soundboard(&ss, NULL, SFX_RST);
// can also try hardware serial with
// Adafruit_Soundboard sfx = Adafruit_Soundboard(&Serial1, NULL, SFX_RST);

// Initalizing and defining states for the breakbeam sensors and the back to zero button
int sensorState = 0, lastState = 0;
int sensorState2 = 0, lastState2 = 0;
int sensorState3 = 0, lastState3 = 0;

char *soundName[] = {

  "01      OGG",
  "02      OGG",
  "03      OGG",
  "04      OGG",
  "05      OGG",
  "06      OGG",
  "07      OGG",
  "08      OGG",
  "09      OGG",
  "10      OGG"
  "11      OGG",
  "12      OGG",
  "13      OGG",
  "14      OGG",
  "15      OGG",
  "16      OGG"
  "17      OGG",
  "18      OGG",
  "19      OGG",
  "20      OGG",
  "21      OGG",
  "22      OGG",
  "23      OGG",
  "24      OGG",
  "25      OGG",
  "26      OGG",
  "27      OGG",
  "24      OGG",
  "25      OGG",
  "26      OGG",
  "27      OGG",
  "28      OGG"
};

char *gol[] = {

  "1004    OGG",
  "1003    OGG"

};


void setup() {
  announcer = 0;
  Serial.begin(9600);
  pinMode(LEDPIN, OUTPUT);

  /*pinMode(SENSORPIN, INPUT);
  digitalWrite(SENSORPIN, HIGH);
  pinMode(SENSORPIN2, INPUT);
  digitalWrite(SENSORPIN2, HIGH);
  pinMode(SENSORPIN3, INPUT);
  digitalWrite(SENSORPIN3, HIGH);      // this is used in IDE < 1.01 */

  pinMode(SENSORPIN, INPUT_PULLUP);
  PinMode(SENSORPIN2, INPUT_PULLUP);
  pinMode(SENSORPIN3, INPUT_PULLUP);

  Rot = 0;
  Blau = 0;

  //Define address for display
  matrix.begin(0x70);

  ss.begin(9600);
  randomSeed(analogRead(0));

}



void loop() {

  a = Rot - Blau;
  b = Blau - Rot;


  // Next 3 lines: Read and save states of the 2 sensors and the back to zero button
  sensorState = digitalRead(SENSORPIN);
  sensorState2 = digitalRead(SENSORPIN2);
  sensorState3 = digitalRead(SENSORPIN3);

  if (Rot / 10)  matrix.writeDigitNum(0, (Rot / 10) );
  matrix.writeDigitNum(1, Rot % 10 );
  matrix.drawColon(true);
  if (Blau / 10)    matrix.writeDigitNum(3, (Blau / 10) );
  matrix.writeDigitNum(4, Blau % 10 );
  matrix.writeDisplay();
  switch (announcer) {
    case 0:
      Serial.println("Start");//print the number
      sfx.playTrack("1002    OGG");
      announcer = 1;
      break;
    case 1:
      if (sensorState == HIGH || sensorState2 == HIGH) {
        randNumber = random(0, 30);
        Serial.println(randNumber);//print the number
        sfx.playTrack(soundName[randNumber]);
      }
      if (Rot == 10 || Blau == 10) announcer = 6;
      if (sensorState == LOW && a <= 2) announcer = 2;
      if (sensorState2 == LOW && b <= 2) announcer = 3;
      if (sensorState == LOW && a >= 3) announcer = 4;
      if (sensorState2 == LOW && b >= 3) announcer = 5;
      break;
    case 2:
      Serial.println("Gol team 1");//print the number
      sfx.stop();
      randGol = random(0, 4);
      Serial.println(randGol);//print the number
      Rot = Rot + 1;
      sfx.playTrack(gol[randGol]);
      announcer = 1;
      break;
    case 3:
      Serial.println("Gol team 2");//print the number
      sfx.stop();
      Blau = Blau + 1;
      sfx.playTrack("1001    OGG");
      announcer = 1;
      break;
    case 4:
      Serial.println("Gol team 1");//print the number
      sfx.stop();
      Serial.println("Hammering");//print the number
      Rot = Rot + 1;
      sfx.playTrack("1005    OGG");
      announcer = 1;
      break;
    case 5:
      Serial.println("Gol team 2");//print the number
      sfx.stop();
      Blau = Blau + 1;
      Serial.println("Hammering");//print the number
      sfx.playTrack("1005    OGG");
      announcer = 1;
      break;
    case 6:
      Serial.println("Finish");//print the number
      sfx.stop();
      sfx.playTrack("1006    OGG");
      a = Rot - Blau;
      b = Blau - Rot;
      matrix.clear();
      announcer = 0;
      break;
  }

  if (sensorState3 && !lastState3) {
  if (!sensorState3 && lastState3) {
    Serial.println("reset");
    Blau = 0;
    Rot = 0;
    matrix.clear();
  }

  lastState = sensorState;
  lastState2 = sensorState2;
  lastState3 = sensorState3;
}

Anyway you shlould only write to the matrix if something has changed, if that doesn't solve anything you could result to using external interrupts for the goal sensors.

Thanks man,

Yes, the sfx.playTrack(soundName[randNumber]) in case 1 is supposed to run in the background as a loop during the whole waiting time (while nothing happens).

I tried to break the switchcases further down (code below) and the response time improved a lot!

/*
  Code adapted from Morgenthaler and Leo at Swiss school www.oszt.ch by Daniel da Silva
*/

// 3 lines importing libraries for the Adafruit display
#include <Wire.h>
#include <Adafruit_GFX.h>
#include "Adafruit_LEDBackpack.h"
#include <Adafruit_Soundboard.h>
#include "SoftwareSerial.h"

long randNumber;
long randGol;
int announcer = 0;

// Initailizing the 7-segment display
Adafruit_7segment matrix = Adafruit_7segment();

// Defining varialbes for the two goals
int Rot;
int Blau;
int a = 0;
int b = 0;

// Defining Arduino's board-LED. For controlling purpose only during coding
#define LEDPIN 13

// Defining the two pins the data connections of the breakbeam sensors
#define SENSORPIN 4
#define SENSORPIN2 2

// Defining the pin for the back to zero button
#define SENSORPIN3 7

#define SFX_TX 3
#define SFX_RX 6
// Connect to the RST pin on the Sound Board
#define SFX_RST 10

// we'll be using software serial
SoftwareSerial ss = SoftwareSerial(SFX_TX, SFX_RX);
// pass the software serial to Adafruit_soundboard, the second
// argument is the debug port (not used really) and the third
// arg is the reset pin
Adafruit_Soundboard sfx = Adafruit_Soundboard(&ss, NULL, SFX_RST);
// can also try hardware serial with
// Adafruit_Soundboard sfx = Adafruit_Soundboard(&Serial1, NULL, SFX_RST);

// Initalizing and defining states for the breakbeam sensors and the back to zero button
int sensorState = 0, lastState = 0;
int sensorState2 = 0, lastState2 = 0;
int sensorState3 = 0, lastState3 = 0;

char *soundName[] = {

  "01      OGG",
  "02      OGG",
  "03      OGG",
  "04      OGG",
  "05      OGG",
  "06      OGG",
  "07      OGG",
  "08      OGG",
  "09      OGG",
  "10      OGG"
  "11      OGG",
  "12      OGG",
  "13      OGG",
  "14      OGG",
  "15      OGG",
  "16      OGG"
  "17      OGG",
  "18      OGG",
  "19      OGG",
  "20      OGG",
  "21      OGG",
  "22      OGG",
  "23      OGG",
  "24      OGG",
  "25      OGG",
  "26      OGG",
  "27      OGG",
  "28      OGG",
  "29      OGG",
  "30      OGG"

};

char *gol[] = {

  "1007    OGG",
  "1008    OGG",
  "1009    OGG"
  "1010    OGG"

};


void setup() {
  announcer = 0;
  Serial.begin(9600);
  pinMode(LEDPIN, OUTPUT);

  /*pinMode(SENSORPIN, INPUT);
  digitalWrite(SENSORPIN, HIGH);
  pinMode(SENSORPIN2, INPUT);
  digitalWrite(SENSORPIN2, HIGH);
  pinMode(SENSORPIN3, INPUT);
  digitalWrite(SENSORPIN3, HIGH);      // this is used in IDE < 1.01 */

  pinMode(SENSORPIN, INPUT_PULLUP);
  pinMode(SENSORPIN2, INPUT_PULLUP);
  pinMode(SENSORPIN3, INPUT_PULLUP);

  Rot = 0;
  Blau = 0;

  //Define address for display
  matrix.begin(0x70);

  ss.begin(9600);
  randomSeed(analogRead(0));

}



void loop() {

  a = Rot - Blau;
  b = Blau - Rot;


  // Next 3 lines: Read and save states of the 2 sensors and the back to zero button
  sensorState = digitalRead(SENSORPIN);
  sensorState2 = digitalRead(SENSORPIN2);
  sensorState3 = digitalRead(SENSORPIN3);

  if (Rot / 10)  matrix.writeDigitNum(0, (Rot / 10) );
  matrix.writeDigitNum(1, Rot % 10 );
  matrix.drawColon(true);
  if (Blau / 10)    matrix.writeDigitNum(3, (Blau / 10) );
  matrix.writeDigitNum(4, Blau % 10 );
  matrix.writeDisplay();
  switch (announcer) {
   
    case 0:
      Serial.println("Start");//print the number
      sfx.playTrack("1002    OGG");
      announcer = 1;
      break;
      
    case 1:
    
      if (sensorState == HIGH || sensorState2 == HIGH) {
        randNumber = random(0, 29);
        Serial.println(randNumber);//print the number
        sfx.playTrack(soundName[randNumber]);
        announcer = 2;
      }

         break;
      

      case 2:
      
      if (Rot == 10 || Blau == 10) announcer = 7;
      if (sensorState == LOW && a <= 2) announcer = 3;
      if (sensorState2 == LOW && b <= 2) announcer = 4;
      if (sensorState == LOW && a >= 3) announcer = 5;
      if (sensorState2 == LOW && b >= 3) announcer = 6;
      break;
    
    
    case 3:
      Serial.println("Gol team 1");//print the number
      sfx.stop();
      randGol = random(0, 3);
      Serial.println(randGol);//print the number
      Rot = Rot + 1;
      sfx.playTrack(gol[randGol]);
      announcer = 1;
      break;
      
    case 4:
      Serial.println("Gol team 2");//print the number
      sfx.stop();
      Blau = Blau + 1;
      sfx.playTrack("1001    OGG");
      announcer = 1;
      break;
      
    case 5:
      Serial.println("Gol team 1");//print the number
      sfx.stop();
      Serial.println("Hammering");//print the number
      Rot = Rot + 1;
      sfx.playTrack("1005    OGG");
      announcer = 1;
      break;
      
    case 6:
      Serial.println("Gol team 2");//print the number
      sfx.stop();
      Blau = Blau + 1;
      Serial.println("Hammering");//print the number
      sfx.playTrack("1005    OGG");
      announcer = 1;
      break;
      
    case 7:
    
      Serial.println("Finish");//print the number
      sfx.stop();
      sfx.playTrack("1006    OGG");
    Blau = 0;
    Rot = 0;
    matrix.clear();
      announcer = 0;
      break;
  }

  if (sensorState3 && !lastState3) {
  if (!sensorState3 && lastState3) {
    Serial.println("reset");
    Blau = 0;
    Rot = 0;
    matrix.clear();
  }

  lastState = sensorState;
  lastState2 = sensorState2;
  lastState3 = sensorState3;
}
}

The problem now is that since the randNumber in case 1 is generated only once in each cycle, the next audio will be played only when the code returns to case 1, like when if somebody scores a goal.
If I generate the randNumber all the time (in milliseconds scale), as before, the whole system gets overload and the IR response time runs down again. Is there a way to generate this randNumber in case one in a loop with a longer delay?

That is a possible solution that I can think about, but maybe there is a simpler and a more appropriated oine.

Thanks!

You should only write to the Matrix if it has new info

  if (Rot / 10)  matrix.writeDigitNum(0, (Rot / 10) );
  matrix.writeDigitNum(1, Rot % 10 );
  matrix.drawColon(true);
  if (Blau / 10)    matrix.writeDigitNum(3, (Blau / 10) );
  matrix.writeDigitNum(4, Blau % 10 );
  matrix.writeDisplay();

Now you are writing all the time. Keep track of what you displayed if it hasn't changed, don't display it !

// we'll be using software serial
SoftwareSerial ss = SoftwareSerial(SFX_TX, SFX_RX);
// pass the software serial to Adafruit_soundboard, the second
// argument is the debug port (not used really) and the third
// arg is the reset pin
Adafruit_Soundboard sfx = Adafruit_Soundboard(&ss, NULL, SFX_RST);
// can also try hardware serial with
// Adafruit_Soundboard sfx = Adafruit_Soundboard(&Serial1, NULL, SFX_RST);

swSerial is a lot more CPU intensive particularly during tx. If you don't need hwSerial for debugging you can switch to hwSerial for you soundboard.
For the Goal sensors you can switch to interrupts rather than polling, but keep in mind that you should switch to hwSerial for the soundboard if you want it to be reliable.
I had difficulty reading you code, it has a lot of comments where i don't need them, white lines and unclear statements that could do with some comments. But i figure if you do these 3 recommendations you will resolve your whole issue and you can do whatever you want in the switch/case.