Get and display sum of values from arrays on multiple boards

I am creating a shooting gallery using Laser Tag guns.
The guns can be set to one of 4 teams (Red, Blue, Green, or Yellow)

I have targets that detect the "hits" from the different guns and add the points to an array.

Currently, I have one target displaying the points for that target.

I will have multiple (16) targets and want the total of all points displayed on the 7 Segment LED from a separate board.

How can I get the values of the arrays on the individual Nano boards and display the total?

The boards will be no more than 4 feet apart from the main board. I will be using a MEGA to control multiple things and display the Total points.

Any idea on how I can poll the individual targets without affecting their ability to record hits?

Here is the code for the one target. Obviously, the 7 segment display will be removed.

Array team_damange has the scores for the 4 teams. I want to have the Mega get the data from the 16 targets. I can use serial communication.

I was thinking of having the Mega poll each Nano (1-16) and get the data. My concern with this is that if the poll happens while a target is "hit", the hit will not be scored. I want to poll but also verify that the data was received.

If I have the Mega just receive, my concern is 2 targets might transmit at the same time if they are hit at the same time.

Another thought was having a second nano on each target that receives data from the target and stores it and that nano is polled by the Mega in sequence.

The current configuration is using I2C via pins 4 and 5 to drive the LED matrix which have unique addresses. Can I somehow use this to communicat witht the Mega?

I might be overthinking this.

Any help would be appreciated.

Thank you in advance
Mark

/*

  Reads a IR packets sent by Light Strike Laser guns
  Determines the Team, Weapon, and Hit Points 
  Data Packets are 32 bits
  Of the 4 bytes in the message, Byte 3 indicates the team (0x07 for Blue (default), 0x04 for Red, 0x05 for Yellow and 0x06 for Green), 
  Byte 2 indicates a count used for the turret bomb mode.  
  Bytes 0  indicates the weapon.  

  We do not need whole bytes since data is only 3 or 5 bits long  

  Data is decoded and led illuminated for team that hit (flash) and stays color of team in the lead
  Resets at 96 points but this will be changed

  7 Segment LED display just for testing.  A Mega will accumulate sores later and display
  
  Sores are stored in array

*/
#include <IRremote.h>
#include <Wire.h> // Enable this line if using Arduino Uno, Mega, etc.
#include <Adafruit_GFX.h>
#include "Adafruit_LEDBackpack.h"

Adafruit_7segment matrix1 = Adafruit_7segment();
Adafruit_7segment matrix2 = Adafruit_7segment();
Adafruit_7segment matrix3 = Adafruit_7segment();
Adafruit_7segment matrix4 = Adafruit_7segment();

int RECV_PIN = 4; //Infrared receiver connected

IRrecv irrecv(RECV_PIN); 

decode_results results;
// the ls_array is used to generate a infrared packet
unsigned int ls_array[33] = {0};

// just a team damage counter
unsigned int team_damange[8] = {0};


void setup()
{
  Serial.begin(9600);
  pinMode(9, OUTPUT); //BLUE LED connected
  pinMode(8, OUTPUT); //GREEN LED connected
  pinMode(7, OUTPUT); //RED LED connected


  //  only for testing
  //LED Matrix will be controlled by MEGA

  
     matrix1.begin(0x70);
     matrix2.begin(0x71);
     matrix3.begin(0x72);
     matrix4.begin(0x73);
     matrix1.print(0);
     matrix1.writeDisplay();
     matrix2.print(0);
     matrix2.writeDisplay();
     matrix3.print(0);
     matrix3.writeDisplay();
     matrix4.print(0);
     matrix4.writeDisplay();




  // Cycle through colors at startup
  //RED
  setLightOn(4);
  delay(250);

  //YELLOW
  setLightOn(5);
  delay(250);

  //GREEN
  setLightOn(6);
  delay(250);

  //BLUE
  setLightOn(7);
  delay(250);

  //OFF
  setLightOff();


  irrecv.enableIRIn(); // Start the receiver

}

void loop() {
  if (irrecv.decode(&results)) {
    rawdump2ls_array(&results, ls_array);

    int team = getColorValue(ls_array);
    //Serial.println(getDamageValue(ls_array));
    //Serial.println(getWeaponValue(ls_array));

    if (team != 0) {
      team_damange[team] += getDamageValue(ls_array);
      setLightOff();
      delay(40);
      setLightOn(team);

      // Heal the team which first reached 96 Damage 
      // capture the flag ;)
      //
      for (int i = 4; i < 8; i++) {
        if (team_damange[i] >= 96) {
          setLightOff();
          delay(100);
          for(int j = 0; j <= 4; j++) {
            setLightOn(8);
            delay(1000);
            setLightOff();
            delay(250);
          }
         
          resetDamage();
        }
      }
    }

    //delay(20);


    // This will be eliminated and the Mega will display the scores
    // team_damage[] will be sent to the Mega and all target scores added and displayed
    //  The target will have just one RGB LED to display the team that is in the lead

    
    for (int i = 4; i < 8; i++) {
                                  Serial.print("Team ");
                                  Serial.print(i);
                                  Serial.print(": ");
                                  Serial.println(team_damange[i]);
                                  if(i==4){
                                          matrix2.print(team_damange[i]);
                                          matrix2.writeDisplay();
                                          }
                                  else if(i==6) {
                                                matrix3.print(team_damange[i]);
                                                matrix3.writeDisplay();
                                                }
                                  else if(i==7) {
                                                matrix1.print(team_damange[i]);
                                               matrix1.writeDisplay();
                                                 }
                                  else if(i==5){
                                             matrix4.print(team_damange[i]);
                                                matrix4.writeDisplay();
                                             }
                                       }

       cleararray(ls_array);
    irrecv.resume();
    
  }

  int bestTeam = 0;
  for (int i = 4; i < 8; i++) {
    if (team_damange[i] > team_damange[bestTeam]) {
      bestTeam = i;
    }
  }
  // Light up with the leading team color
  setLightOn(bestTeam);
  
}
void cleararray(unsigned int ls_array[]){
   for (int i = 1; i < 33; i++) {
                        ls_array[i] = 0;
                                  
                               }
 }
void resetDamage() {
  for (int i = 4; i < 8; i++) {
    team_damange[i] = 0;
  }
}

void setLightOff() {
  digitalWrite(9, LOW);
  digitalWrite(8, LOW);
  digitalWrite(7, LOW);
}




void setLightOn(int color) {
  if (color == 7) {
    //BLUE
    digitalWrite(9, HIGH);
    digitalWrite(8, LOW);
    digitalWrite(7, LOW);
  } else if (color == 6) {
    //GREEN
    digitalWrite(9, LOW);
    digitalWrite(8, HIGH);
    digitalWrite(7, LOW);
  } else if (color == 5) {
    //YELLOW
    digitalWrite(9, LOW);
    digitalWrite(8, HIGH);
    digitalWrite(7, HIGH);
  } else if (color == 4) {
    //RED
    digitalWrite(9, LOW);
    digitalWrite(8, LOW);
    digitalWrite(7, HIGH);
  } else if (color == 8) {
    //MAGENTA
    digitalWrite(9, HIGH);
    digitalWrite(8, LOW);
    digitalWrite(7, HIGH);
  }

}

int getColorValue(unsigned int ls_array[]) { // don't need whole byte  just bits 6-8
  return getLSValue(ls_array, 8, 6);
}

int getDamageValue(unsigned int ls_array[]) {// don't need whole byte  just bits 28-32
  return getLSValue(ls_array, 32, 28);
}

int getWeaponValue(unsigned int ls_array[]) {// don't need whole byte  just bits 20-24
  return getLSValue(ls_array, 24, 20);
}



int getLSValue(unsigned int ls_array[], int maxBit, int minBit) {// decode Binary to decimal
  int val = 0;
  int loopcount = 1;
  for (int i = maxBit; i >= minBit; i--) {
    val += ls_array[i] * loopcount;
    loopcount = loopcount * 2;
  }
  return val;
}

void rawdump2ls_array(decode_results *results, unsigned int ls_array[]) {// dump read into array
  int count = results->rawlen;

  if (count == 66) {
    for (int i = 0; i < count; i++) {
      if ((i % 2) == 0) {
        if ((int)results->rawbuf[i]*USECPERTICK > 3000) {
          ls_array[i / 2] = 1;
        } else {
          ls_array[i / 2] = 0;
        }
      }
    }
  }
}

I'd favour SPI or RS-485 (half duplex) for a tolerant communication interface. When a target is selected, it sends data within a certain time frame, with hit detection taking precedence over transmission.

DrDiettrich: I'd favour SPI or RS-485

I tried RS485 and it was incredibly slow. I will give SPI a shot.

Neither SPI nor RS-485 imply a mandatory speed. Use a higher baudrate with RS-485, eventually multiple Serial ports.

Polling sounds best. It should not be hard to poll a few hundred targets in a second. Or a few targets a hundred times each.

The target should remember that it was hit and has not yet transmitted that value to the master. That way you don't lose any hits.