gioblu / PJON

PJON (Padded Jittering Operative Network) is an experimental, arduino-compatible, multi-master, multi-media network protocol.
Other
2.73k stars 239 forks source link

Problem (PJON_BUSY Error) using ThroughSerial strategy in multi-master mode #396

Closed AlirezaSalehy closed 2 years ago

AlirezaSalehy commented 3 years ago

Hi there! First i think that i have to appreciate this great open source network library, high regard for contributors. I'm working on a project in which i'm trying to establish a multi-master network over RS485 physical layer, with bus topology. I have noticed that the documentation of ThroughSerial says multi-master is supported using slotted ALOHA as MAC sublayer and that is really great. So i tried to test how collisions are handled and measure network reliability. The test consists of 3 nano boards. one that broadcasts a message periodically (say every 3 secs.) and two other nanos that reply to first nano as soon as they received the broadcasted message (which happens simultaneously for 2) . This way i deliberately generated a collision case, hoping that collision will be handled and the first nano will receive response of two others after some retransmission. But the bus failed completely that even first nano could hardly transmit periodic broadcast message at the right time, and second and third nanos could not send response even once. bus.send_packet_blocking() most of the times (say 90%) returns PJON_BUSYwhen called in the loop() at first nano. Also i receive PJON_BUSY error for both other nanos.

Here is the code for first nano:

#include <SoftwareSerial.h>
#include <PJONThroughSerial.h>

#define DEVICE_ID 1
#define CNTRL 5

SoftwareSerial mySerial(7, 6); // RX, TX
PJONThroughSerial bus(DEVICE_ID);

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW); // Initialize LED 13 to be off

  mySerial.begin(57600);
  Serial.begin(115200);

  bus.strategy.set_serial(&mySerial);
  bus.strategy.set_enable_RS485_pin(CNTRL);
  bus.set_communication_mode(PJON_HALF_DUPLEX);
  bus.set_receiver(receiver_function);
  bus.set_acknowledge(true);
  bus.begin();
};

void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) {
  /* Make use of the payload before sending something, the buffer where payload points to is
     overwritten when a new message is dispatched */
  uint8_t tx_id = packet_info.tx.id;
  uint8_t counter = payload[0];

  Serial.println(tx_id);
  Serial.println(counter);
  Serial.println();

  digitalWrite(LED_BUILTIN, HIGH);
  delay(30);
  digitalWrite(LED_BUILTIN, LOW);
  delay(30);
};

uint8_t count = 0;

void loop() {
  bus.receive();   
  bus.update();
  uint16_t res = bus.send_packet_blocking(PJON_BROADCAST, &count, 1); // Broad cast by sending to device with id = 0
  Serial.println(res);
  count++;
  delay(3000);
};

And code for two others:

#include <SoftwareSerial.h>
#include <PJONThroughSerial.h>

#define DEVICE_ID 2 // Second nano's ID = 2, and Third's ID = 3  
#define CNTRL A3

SoftwareSerial mySerial(A1, A2); // RX, TX
PJONThroughSerial bus(DEVICE_ID);

void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) {
  /* Make use of the payload before sending something, the buffer where payload points to is
     overwritten when a new message is dispatched */
  uint8_t counter = payload[0];
  uint8_t tx_id = packet_info.tx.id;

  if(tx_id == 1) {
    delay(100);

    uint16_t res = bus.reply(&counter, 1);
    Serial.println(res);

    digitalWrite(LED_BUILTIN, HIGH);
    delay(30);
    digitalWrite(LED_BUILTIN, LOW);
    delay(30);

  }
}

void setup() {
  // Initialize LED 13 to be off
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
  // Initialize Serial instance used for PJON communication
  mySerial.begin(57600);
  Serial.begin(57600);

  bus.strategy.set_serial(&mySerial);
  bus.strategy.set_enable_RS485_pin(CNTRL);
  bus.set_communication_mode(PJON_HALF_DUPLEX);
  bus.set_acknowledge(true);
  bus.set_receiver(receiver_function);
  bus.begin();

}

void loop() {
    bus.receive();
    bus.update();
};

So i need to know whether you guys can regenerate this case and see if same problem arise or i am doing something wrong that face this problem.

Thank you for your attentions. Best regards!

Ali R. Salehy

gioblu commented 2 years ago

Ciao @A-R-S-D I am sorry for the very late response. I suspect you are experiencing a very common issue. The problem is the following. To understand if a collision occurred the device has only the chance to check the rx buffer to see if any communication occurred, or is occurring. To reduce the amount of PJON_BUSY you need to receive for a small time before attempting any transmission, that would discard data in the rx buffer and let you transmit freely. Collisions may occur, although the system should work thanks to retransmissions.