Problems implementing CSMA/CA Protocol (ARDUINO + RF24L01)
good night everyone, code i'm posting here implementation of wireless connection operating 2 transmiters , 1 receiver. receiver able transmitt aswell due need send "manual" ack when succssefully receives frame. problem want both transmitters compete transmit although, happening is, jamming each other , cant transmit anything. if operate 1 transmitter transmition goes expected. sorry english, here 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 duas estações transmissoras
//estrutura meu pacote.
typedef struct pacote {
byte startbit = 0;
byte stopbit = 1;
byte id_trama; //id 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; < 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 crc dos dados que vou ler.... -> se esse valor = 0, bem rececionado.
//serial.print("\n\ncumpriu testes de startbit e stopbit");
//serial.print("\nvalor crc: ");
//serial.print(incoming);
if (data.crc == 0) { //crc = 0 , sem erros
//serial.print("\ncumpriu testes 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 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 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 pacote
char payload[3] = {0x81, 0x89, 0x00}; //meus dados 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("\n**************transmissor 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 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; < 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 = 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 = 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 ouvir , comecou 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 trama...");
dados.id_trama;
lti.stoplistening();
lti.write(&dados, sizeof(pacote)); //envio trama outra vez
dados.id_trama++;
lti.startlistening();
serial.print("\nvou reenviar 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 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 basicly same transmitter 1 pipes change. tip helpfull!
thank guys
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 duas estações transmissoras
//estrutura meu pacote.
typedef struct pacote {
byte startbit = 0;
byte stopbit = 1;
byte id_trama; //id 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; < 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 crc dos dados que vou ler.... -> se esse valor = 0, bem rececionado.
//serial.print("\n\ncumpriu testes de startbit e stopbit");
//serial.print("\nvalor crc: ");
//serial.print(incoming);
if (data.crc == 0) { //crc = 0 , sem erros
//serial.print("\ncumpriu testes 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 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 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 pacote
char payload[3] = {0x81, 0x89, 0x00}; //meus dados 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("\n**************transmissor 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 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; < 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 = 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 = 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 ouvir , comecou 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 trama...");
dados.id_trama;
lti.stoplistening();
lti.write(&dados, sizeof(pacote)); //envio trama outra vez
dados.id_trama++;
lti.startlistening();
serial.print("\nvou reenviar 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 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 basicly same transmitter 1 pipes change. tip helpfull!

up
Arduino Forum > Using Arduino > Programming Questions > Problems implementing CSMA/CA Protocol (ARDUINO + RF24L01)
arduino
Comments
Post a Comment