Unreliable node-to-node communication

  • Let me start by acknowledging that my project is not typical of what I've seen around here. I am making an interactive art installation, where there will be many (~20) networked nodes positioned in a fixed grid. This array will be suspended in the air so that visitors will walk below the nodes. In this case, there is no controller - each node is programmed with a fixed ID (and a list of the IDs of its immediate neighbors). Each node has a PIR motion sensor pointing down, that when triggered sends a message to its neighbors.

    So in this situation, each sensor node must be capable of sending and receiving multiple messages in a responsive manor. I've built a prototype with 4 of these nodes (plus a gateway). In this prototype, each triggered node sends a message to two neighbors. The system does work as intended, but not reliably so. Perhaps 1/3 of the time, messages are not received at all. Serial debugging indicates that all messages are being sent, and also pass through the gateway, but sometimes just aren't received.

    My theory is that the node is otherwise occupied upon message arrival and so fails to receive them. I have kept the main run loop simple, but are there any techniques for not losing messages? In this project, the node does have another small function, which is to tell another microcontroller to light up some leds - and for this I am using a simple I2C connection. I wouldn't think that the time it takes to perform a tiny Wire transmission would block incoming messages, but maybe that's it.

    Here is my node code (which is running on Adafruit Trinket Pro 5V 16Mhz):

    #define MY_DEBUG 
    #define MY_RADIO_NRF24 
    #define MY_NODE_ID 1 // Assign a fixed id
    #include <MySensors.h>
    #include <Wire.h>
    #define PIN_MOTION 8 // digital input triggered by motion sensor
    #define LED_I2C_ADDRESS 1 // i2c address for triggering LED animation
    #define LOOP_TIME 100 // main loop duration in milliseconds
    // initialize messages
    MyMessage msg1(1, V_TRIPPED);
    MyMessage msg2(1, V_TRIPPED);
    boolean isActive = false;
    void setup() {
      Serial.begin(115200); // start serial for debug output
      Wire.begin(); // join i2c bus
      pinMode(PIN_MOTION, INPUT);
    void presentation()  {
      // register sensor to gw
      present(1, S_MOTION);
    void receive(const MyMessage &message) {
      // neighbor triggers half lights
    void loop() {
      boolean isMotionDetected = digitalRead(PIN_MOTION) == HIGH; 
      if (isMotionDetected) {
        if (!isActive) {
          isActive = true;
          // send a message to neighbor nodes
          // TODO: more elegantly define node relationships
          if (MY_NODE_ID == 1 || MY_NODE_ID == 4) {
          } else  {
      } else {
        isActive = false;
    void triggerLights(uint8_t val) {