Problems implementing CSMA/CA Protocol (ARDUINO + RF24L01)

Good night everyone, this code i'm posting here is an implementation of a wireless connection operating with 2 transmiters and one receiver. Receiver is able to transmitt aswell due to my need to send "manual" ACK when he succssefully receives a frame. My problem is i want both transmitters to compete for transmit although, what is really happening is, they are jamming each other and cant transmit anything. If i operate with only one transmitter the transmition goes as expected. Sorry for my english, so here is the code:

RECEIVER

//RECETOR
#include <SPI.h>
#include <nRF24L01.h>
#include "RF24.h"
#include <printf.h>

//RF24 LTI(9, 10); //pinos pa com
const int pinCE = 9;
const int pinCSN = 10;
RF24 LTI(pinCE, pinCSN);
const uint64_t rAddress[] = {0xB00B1E50D2LL, 0xB00B1E50C3LL}; // Endereços dos pipes para receber dados das duas estações transmissoras
const uint64_t wAddress[] = {0xB00B1E50B1LL, 0xB00B1E50A4LL}; // Endereços dos pipes para enviar dados para as duas estações transmissoras

//estrutura do meu pacote.

typedef struct pacote {
byte startBit = 0;
byte stopBit = 1;
byte id_trama; //ID do pacote
char payload[3] = "";
unsigned char crc;
char rede[3] = "";
};

typedef struct tramaControlo {
byte ACK;
pacote id_trama;

};

void setup() {
//configs
Serial.begin(115200); //baud
Serial.println("Recetor**");

LTI.begin();
LTI.setPALevel(RF24_PA_MAX);
LTI.setChannel(120);
LTI.setDataRate(RF24_2MBPS);
LTI.enableDynamicPayloads();
LTI.setRetries(15, 15);

LTI.openReadingPipe(1, rAddress[0]);
LTI.openReadingPipe(2, rAddress[1]);
LTI.startListening();

}

const unsigned char CRC7_POLY = 0x91;

char getCRC(char message[], char length)
{
unsigned char i, j, crc = 0;

for (i = 0; i < length; i++)
{
crc ^= message*;*

  • for (j = 0; j < 8; j++)*
  • {*
  • if (crc & 1)*
  • crc ^= CRC7_POLY;*
  • crc >>= 1;*
  • }*
    }
    return crc;
    }
    void loop() {
    pacote data;
    tramaControlo ok;
    byte startB = 0; //B11111110;
    byte stopB = 1; //B00000001;
    char network[3] = "aa";
    unsigned char incoming;
    byte pipeNo = 0;
    if (LTI.available(&pipeNo)) {
  • while (LTI.available(&pipeNo)) {*
  • LTI.read(&data, sizeof(pacote)); //Pega na trama , lê*
  • }*
  • if (startB == data.startBit) {*
  • if (stopB == data.stopBit) {*
  • data.crc = getCRC(data.payload, 3); //Vejo o valor do CRC dos dados que vou ler.... -> Se esse valor = 0, bem rececionado.*
  • //Serial.print("\n\nCumpriu testes de startbit e stopbit");*
  • //Serial.print("\nValor do CRC: ");*
  • //Serial.print(incoming);*
  • if (data.crc == 0) { //crc = 0 , sem erros*
  • //Serial.print("\nCumpriu testes do CRC");*
  • if (network == data.rede) {*
  • }*
  • }*
  • }*
  • Serial.print("\nRecebi dados da estacao: ");*
  • Serial.print(pipeNo);*
  • Serial.print("\nTrama numero: ");*
  • Serial.print(data.id_trama);*
  • enviarAckCorreto(pipeNo);*
  • Serial.print("\nACK ENVIADO");*
  • }*
  • else*
  • {*
  • enviarNackCorreto(pipeNo);*
  • Serial.print("\nNACK ENVIADO");*
  • }*
    }
    }
    //funcao para enviar ACK para a estação correta
    void enviarAckCorreto(byte papa) {
    tramaControlo ok;
    LTI.stopListening();
    LTI.openWritingPipe(wAddress[papa - 1]);
    ok.ACK = 1;
    LTI.write(&ok, sizeof(tramaControlo));
    LTI.startListening();
    }
    //funcao para enviar NACK para a estação correta
    void enviarNackCorreto(byte papa) {
    tramaControlo ok;
    LTI.stopListening();
    LTI.openWritingPipe(wAddress[papa - 1]);
    ok.ACK = 0;
    LTI.write(&ok, sizeof(tramaControlo));
    LTI.startListening();
    }
    TRANSMITTER 1:
    //TRANSMISSOR 1
    #include <SPI.h>
    #include <nRF24L01.h>
    #include "RF24.h"
    #include <printf.h>
    const int pinCE = 9;
    const int pinCSN = 10;
    RF24 LTI(pinCE,pinCSN); //RF24 radio(9, 10);
    const uint64_t wAddress = 0xB00B1E50D2LL; //Pipe de transmissão de tramas
    const uint64_t rAddress = 0xB00B1E50B1LL; //Pipe de receção de tramas
    typedef struct pacote {
    byte startBit = 0; //Combinacao binário
    byte stopBit = 1; //Combinacao binária
    byte id_trama; //ID do pacote
    char payload[3] = {0x81, 0x89, 0x00}; //meus dados a serem enviados
    unsigned char crc;
    char rede[3] = "aa";
    };
    typedef struct tramaControlo {
    byte ACK; //ACK = 1 NACK = 0
    byte ackCount;
    //byte estacao;
    };
    bool tx = 1;
    int tempo_slot = 4;
    /SETUP****/
    void setup() {
    //configs
    Serial.begin(115200); //baud
    Serial.println("\nTransmissor 1****");
    LTI.begin();
    LTI.setPALevel(RF24_PA_MAX);
    LTI.setChannel(120);
    LTI.setDataRate(RF24_2MBPS);
    LTI.setRetries(15, 15);
    LTI.enableDynamicPayloads();
    LTI.openWritingPipe(wAddress); //open writing or transmit pipe
    LTI.openReadingPipe(1,rAddress); //open reading or recieve pipe
    LTI.stopListening(); //go into transmit mode
    //Serial.println("HELLO!");
    }
    /CRC******/
    const unsigned char CRC7_POLY = 0x91;
    char getCRC(char message[], char length)
    {
    unsigned char i, j, crc = 0;
    for (i = 0; i < length; i++)
    {
    _ crc ^= message*;_
    _
    for (j = 0; j < 8; j++)_
    _
    {_
    _
    if (crc & 1)_
    crc ^= CRC7_POLY;
    _
    crc >>= 1;_
    _
    }_
    _
    }_
    return crc;
    _
    }_
    _/Transmissor**********/
    void loop() {
    //config trama e defs necessárias
    pacote dados;
    tramaControlo ok; //trama controlo
    dados.payload[2] = getCRC(dados.payload, 2);
    dados.crc = getCRC(dados.payload, 3);
    Serial.print("CRC: ");
    Serial.print(dados.crc);
    if (tx == 1)
    *{ *
    * delay(4); // atraso ISF*
    * bool estado_meio = false;
    int fator_k;
    _
    LTI.startListening();*

    * if (LTI.testCarrier()) {*
    * Serial.print("\n Canal ocupado, esperar...");*
    * fator_k = rand() % 10;
    _
    int i = 0;_
    while (i < fator_k)
    _
    {_
    _
    delay(1);_
    _
    i++;_
    _
    }_
    estado_meio = true;*

* }*
* else if(estado_meio==false)
_
{_
_
LTI.stopListening();_
_
Serial.println("\nCanal aparenta estar livre. Vou esperar um tempo random e enviar........\n");_
_
delay(4);_
_
int i = 0;_
fator_k = rand() % 10;
while (i < fator_k)
_
{_
_
delay(1);_
_
i++;_
_
}_
unsigned long tempo_inicio = micros(); //mal implementado*

* if (!LTI.write(&dados, sizeof(pacote))) { //escrever o meu pacote*
* Serial.println("\nFalhou o envio....\n");*
* }*
* LTI.startListening(); //começo a ouvir , comecou a enviar*
* unsigned long espera = micros();*
* boolean timeout = false;*
* while (!LTI.available()) {*
* if ( (micros() - espera) > 200000) {*
* timeout = true;*
* break;*
* }*
* }*
* if (timeout)*
* {*
* Serial.print("\nTIMEOUT");*
* delay(1500);*
* Serial.print("\nTentar enviar novamente a trama...");*
* dados.id_trama;
_
LTI.stopListening();_
_
LTI.write(&dados, sizeof(pacote)); //envio trama outra vez*_
* dados.id_trama++;
_
LTI.startListening();_
_
Serial.print("\nVou reenviar a trama: ");_
_
Serial.print(dados.payload);_
_
Serial.print("\nID da trama: ");_
Serial.println(dados.id_trama);
_
}_
_
else {_
_
LTI.read(&ok, sizeof(tramaControlo));_
unsigned long tempo_fim = micros();
_
if (ok.ACK == 1) { //Recebeu ACK actualizar dados*_
* Serial.print("\nTrama enviada: ");*
* Serial.print(dados.payload);*
* Serial.print("\nTamanho da trama: ");*
* Serial.print(sizeof(pacote));*
* Serial.print("\nACK recebido "); //esperamos aqui ok.ACK = 1 && ok.NACK = 0;*
* Serial.print("\nID da trama : ");*
* Serial.print(dados.id_trama);
_
Serial.print("\nRTT ");_
Serial.print(tempo_fim - tempo_inicio);
_
Serial.println(" microsegundos");_
dados.id_trama++; //incremento para o proximo pacote*

* LTI.stopListening();*
* Serial.println("Vou enviar o proximo....!\n"); //Ter em conta que pode falhar no envio do transmissor outra vez!!!!!*

* LTI.stopListening();*
* }*
* else { //Recebeu NACK enviar trama anterior*
* dados.id_trama; //reenvia pacote com ID anterior*
* //Reenvia pacote anterior.*
* Serial.print("\nTrama enviada: ");*
* Serial.print(dados.payload);*
* Serial.print("\nNACK recebido "); //esperamos aqui ok.ACK = 1 && ok.NACK = 0;*
* Serial.print("\nID da trama : ");*
* Serial.print(dados.id_trama);
_
Serial.print("\nRTT ");_
Serial.print(tempo_fim - tempo_inicio);
_
Serial.println(" microseconds");_
_
LTI.stopListening();_
_
//continua();_
dados.id_trama++; //incrementa para o proximo*

* }*
* }*
* }*
* LTI.stopListening();*
}
}
Transmitter 2 is basicly the same as transmitter 1 only pipes will change. Any tip will be helpfull! :slight_smile: thank you guys

UP

My problem is i want both transmitters to compete for transmit although ...

that's a really bad plan ...

Dan95:
that's a really bad plan ...

That's the project i have in hands.

Please modify your post and use the code button </> so your code looks like this and is easy to copy to a text editor. See How to use the Forum Your code is much too long for me to study quickly without copying to a text editor.

Have a look at the second example in this Simple nRF24L01+ Tutorial. It uses the ackPayload feature to get a quick response without any risk of collisions.

There is absolutely no need for your program to implement collision detection. That is all taken care of within the nRF24. Just set the number of retries and the timeout to suitable values. And make sure that your code does not cause unnecessary contention.

...R