Que tal montar uma rede de
arduinos? Então, hoje vamos empregar os Arduinos Nano (RF-Nano) utilizando
rádio NRF24L01 para fazer a transmissão de mensagens entre eles. Confira no
vídeo!
RECURSOS USADOS
- 2 ou mais RF-Nano
PINAGEM
Arduino Uno com NRF24L01+
O ATmega328 já usa
D9,D10,D11,D12, e D13 não podem ser usados
BIBLIOTECAS
RF24 by TMRh20
FLUXOGRAMA MASTER
CÓDIGO
Declarações e variáveis
#include <SPI.h> #include <RF24.h> //Quantidade de nós slave #define NODES_COUNT 2 //Nomeamos requisição chamada 'count'. Neste exemplo vamos fazer apenas um request chamado count //onde o slave nos retornará a quantidade de requisições que ele recebeu. //Você pode criar novos tipos de requisições de acordo com o que queira, como valores de sensores por exemplo. #define REQUEST_VALUE_COUNT "count" //Intervalo entre as requisições que este ESP fará #define REQUEST_INTERVAL 1000 //Quantidade de tempo de espera máxima para uma resposta #define TIMEOUT 3000 //Objeto responsável pela comunicação via rádio //Pino 10 = Chip enable, Pino 9 = chip select RF24 radio(10, 9); //Endereço dos nós slave. Cada slave que for utilizar deve-se trocar o 'address' (no Slave.ino) para um deste array. //5 caracteres para cada endereço. Se for abrir várias leituras simultâneas, a partir do segundo endereço o 1 primeiro //caractere deve ser diferente e o resto dos bytes iguais. Neste exemplo estamos lendo um de cada vez, //desligando a leitura do outro enquanto isso. uint8_t addresses[NODES_COUNT][6] = {"1node", "2node"}; //Índice do slave que estamos nos comunicando atualmente int currentSlaveIndex = 0; //Estrutura de exemplo de uma requisição que o master vai fazer para os slaves //Modifique de acordo com a sua necessidade //Deve ser igual no código dos slaves struct Request { unsigned long millis; char message[20]; }; //Estrutura de exemplo de uma resposta que os slaves enviarão para o master //Modifique ou adicione novas estruturas de acordo com a sua necessidade //Deve ser igual no código dos slaves struct Response { unsigned long millis; int value; };
setup
void setup() { Serial.begin(115200); //Inicializa o objeto que vai controlar o rádio radio.begin(); Serial.println("Master Started"); }
loop
void loop() { //Envia requisição para o slave atual. Retorna true se conseguiu ou false caso contrário if(sendRequest()) { //Se chegou aqui a requisição foi bem sucedida Serial.print("Successfully sent request to "); Serial.println((char*)addresses[currentSlaveIndex]); //Tenta ler a resposta tryToReadResponse(); } else { //Se chegou aqui houve erro no envio da requisição ou no recebimento do ACK Serial.print("Failed to send request to "); Serial.println((char*)addresses[currentSlaveIndex]); } //Modifica o índice para o próximo slave currentSlaveIndex++; //Se estourou a quantidade de índices, voltamos para o 0 if(currentSlaveIndex >= NODES_COUNT) { currentSlaveIndex = 0; } //Espera o tempo estabelecido delay(REQUEST_INTERVAL); }
sendRequest
bool sendRequest() { //Para enviar precisamos desativar o modo de recebimento radio.stopListening(); //Ativa a escrita no endereço do slave atual radio.openWritingPipe(addresses[currentSlaveIndex]); //Cria uma requisição dizendo qual o tempo de boot (apenas como exemplo de dado que pode ser enviado) //e mensagem pedindo o valor do contador que o slave mantém e incrementa a cada requisição Request request = {millis(), REQUEST_VALUE_COUNT}; //Faz o envio. Retorna true se o envio for confirmado (está com ACK ativado) ou false caso contrário return radio.write(&request, sizeof(request)); }
tryToReadResponse
void tryToReadResponse() { //Informa o endereço de leitura como sendo o endereço do slave atual radio.openReadingPipe(0, addresses[currentSlaveIndex]); //Ativa o recebimento de dados radio.startListening(); //Se conseguiu obter uma resposta dentro do tempo máximo estabelecido if(gotResponseInTime()) { //Faz a leitura da resposta Response response; radio.read(&response, sizeof(response)); //Mostra no monitor serial printResponse(response); } }
gotResponseInTime
bool gotResponseInTime() { //Marca o tempo que começou unsigned long start = millis(); //Enquanto o slave não enviar nada while (!radio.available()) { //Verifica se passou do tempo de espera if(millis() - start > TIMEOUT) { Serial.print((char*)addresses[currentSlaveIndex]); Serial.println(" response timeout"); //Se chegou aqui significa que o slave demorou além do tempo de espera para nos enviar uma resposta return false; } } //Se chegou aqui significa o slave enviou a resposta dentro do tempo return true; }
printResponse
void printResponse(Response response) { //Mostra no monitor serial o endereço, valor da contagem de requisições e tempo de boot do slave Serial.print("Received response from "); Serial.print((char*)addresses[currentSlaveIndex]); Serial.print(" with value "); Serial.print(response.value); Serial.print(". Sender boot time "); Serial.print(response.millis); Serial.println("ms."); }
FLUXOGRAMA SLAVE
CÓDIGO
Declarações e variáveis
#include <SPI.h> #include <RF24.h> //Nomeamos uma requisição chamada 'count' assim como está no código do master #define REQUEST_VALUE_COUNT "count" //Objeto responsável pela comunicação via rádio //Pino 10 = Chip enable, Pino 9 = chip select RF24 radio(10, 9); //Endereço deste slave. Deve ser um dos que estão no array de endereços do master. //Cada slave deve possuir um diferente. const uint8_t address[6] = "1node"; //Contador de requisições int count = 0; //Estrutura de exemplo de uma requisição que o master vai fazer para os slaves //Modifique de acordo com a sua necessidade //Deve ser igual no código do master struct Request { unsigned long millis; char message[20]; }; //Estrutura de exemplo de uma resposta que os slaves enviarão para o master //Modifique ou adicione novas estruturas de acordo com a sua necessidade //Deve ser igual no código do master struct Response { unsigned long millis; int value; };
setup
void setup() { Serial.begin(115200); //Inicializa o objeto que vai controlar o rádio radio.begin(); //Informa o endereço de leitura radio.openReadingPipe(0, address); //Ativa o recebimento de dados radio.startListening(); Serial.print("Slave "); Serial.print((char*)address); Serial.println(" Started"); }
loop
void loop() { //Se chegou algo do master if (radio.available()) { //Fazemos a leitura da requisição e enviamos uma resposta readAndAnswerRequest(); } }
readAndAnswerRequest
void readAndAnswerRequest() { //Fazemos a leitura da requisição Request request; radio.read(&request, sizeof(request)); //Incrementa o contador de requisições count++; //Mostramos a requisição no monitor serial printRequest(request); //Se a mensagem é igual a string que está em 'REQUEST_VALUE_COUNT' //significa que é uma requisição para enviar o contador //Este é apenas um exemplo, mas você pode adicionar outras requisições como //valores de sensores if(strcmp(request.message, REQUEST_VALUE_COUNT) == 0) { //Envia a respostas sendCountResponse(); } }
printRequest
void printRequest(Request request) { //Mostra no monitor serial a mensagem recebida e o tempo de boot do master como exemplo Serial.print("Got request with message '"); Serial.print(request.message); Serial.print("'. Sender boot time "); Serial.print(request.millis); Serial.println("ms."); }
sendCountResponse
void sendCountResponse() { //Para enviar precisamos desativar o modo de recebimento radio.stopListening(); //Informamos o endereço para onde iremos enviar radio.openWritingPipe(address); //Cria uma estrutura de reposta contendo o tempo de boot atual deste slave e o contador de requisições Response response = {millis(), count}; //Faz o envio da resposta. Retorna true se bem sucedido ou false caso contrário if (!radio.write(&response, sizeof(response))) { Serial.println("failed"); } //Reativa o modo de recebimento radio.startListening(); }
0 Comentários