Interface nRF24L01 com Arduino: servo motor de controle

Tempo de leitura: 8 minutes

Enquanto a Internet das coisas (IoT), Indústria 4.0, comunicação de máquina a máquina etc. estão se tornando cada vez mais populares, a necessidade de comunicação sem fio tornou-se obrigatória, com mais máquinas / dispositivos para se comunicarem na nuvem. Os designers usam muitos sistemas de comunicação sem fio como Bluetooth Low Energy (BLE 4.0), Zigbee, Módulos Wi-Fi ESP43, Módulos RF 433MHz, Lora, nRF etc, e a seleção do meio depende do tipo de aplicação em que está sendo usado.

Entre todos, um meio sem fio popular para comunicação de rede local é o nRF24L01. Esses módulos operam em 2,4 GHz (banda ISM) com taxa de transmissão de 250 Kbps a 2 Mbps, o que é legal em muitos países e pode ser usado em aplicações industriais e médicas. Alega-se também que, com antenas adequadas, esses módulos podem transmitir e receber até uma distância de 100 metros entre eles. Interessante né !!? Portanto, neste tutorial, aprenderemos mais sobre esses módulos nRF24l01 e como fazer a interface com uma plataforma de microcontrolador como o Arduino. Também compartilharemos algumas soluções para os problemas mais comuns enfrentados durante o uso deste módulo.

 

Conhecendo o Módulo RF nRF24L01

Os módulos nRF24L01 são módulos transceptores, o que significa que cada módulo pode enviar e receber dados, mas, como são half-duplex, podem enviar ou receber dados ao mesmo tempo. O módulo possui o IC genérico nRF24L01 da Nordic semicondutores que é responsável pela transmissão e recepção de dados. O IC se comunica usando o protocolo SPI e, portanto, pode ser facilmente conectado a qualquer microcontrolador. Fica muito mais fácil com o Arduino, pois as bibliotecas estão prontamente disponíveis. A pinagem de um módulo nRF24L01 padrão é mostrada abaixo

O módulo tem tensão de operação de 1,9V a 3,6V (normalmente 3,3V) e consome muito menos corrente de apenas 12 mA durante a operação normal, o que o torna eficiente em bateria e, portanto, pode até funcionar com células tipo moeda. Mesmo que a tensão de operação seja de 3,3V, a maioria dos pinos são tolerantes a 5V e, portanto, podem ter interface direta com microcontroladores de 5V como o Arduino. Outra vantagem de usar esses módulos é que, cada módulo possui 6 Pipelines. Ou seja, cada módulo pode se comunicar com 6 outros módulos para transmitir ou receber dados. Isso torna o módulo adequado para a criação de redes em estrela ou em malha em aplicativos de IoT. Além disso, eles têm uma ampla faixa de endereços de 125 IDs exclusivos, portanto, em uma área fechada, podemos usar 125 desses módulos sem interferir uns com os outros.

Interface nRF24L01 com Arduino

Neste tutorial, aprenderemos como fazer a interface do nRF24L01 com o Arduino controlando o servo motor conectado a um Arduino variando o potenciômetro do outro Arduino. Para simplificar, usamos um módulo nRF24L01 como transmissor e o outro como receptor, mas cada módulo pode ser programado para enviar e receber dados individualmente.

O diagrama de circuito para conectar o módulo nRF24L01 com o Arduino é mostrado abaixo. Para variar, usei o UNO para o lado do receptor e o Nano para o lado do transmissor. Mas a lógica de conexão permanece a mesma para outras placas Arduino como mini, mega também.

 

Lado do receptor: conexões do módulo Arduino Uno nRF24L01

Como dito anteriormente, o nRF24L01 se comunica com a ajuda do protocolo SPI. No Arduino Nano e UNO, os pinos 11, 12 e 13 são usados para comunicação SPI. Conseqüentemente, conectamos os pinos MOSI, MISO e SCK do nRF aos pinos 11, 12 e 13, respectivamente. Os pinos CE e CS são configuráveis pelo usuário, usei os pinos 7 e 8 aqui, mas você pode usar qualquer pino alterando o programa. O módulo nRF é alimentado pelo pino de 3,3 V no Arduino, que na maioria dos casos funcionará. Caso contrário, uma fonte de alimentação separada pode ser tentada. Além de fazer a interface com o nRF, também conectei um servo motor ao pino 7 e o alimentei através do pino 5V no Arduino. Da mesma forma, o circuito do transmissor é mostrado abaixo.

 

Lado do transmissor: Conexões do módulo Arduino Nano nRF24L01

As conexões para o transmissor também são as mesmas, além disso, usei um potenciômetro conectado ao pino de aterramento de 5 V do Arduino. A tensão analógica de saída que varia de 0 a 5 V está conectada ao pino A7 do Nano. Ambas as placas são alimentadas pela porta USB.

Trabalhando com nRF24L01 + Módulo Transceptor Sem Fio

No entanto, para que nosso nRF24L01 funcione sem ruído, devemos considerar o seguinte. Venho trabalhando neste nRF24L01 + há muito tempo e aprendi os seguintes pontos que podem ajudá-lo a não ser atingido em uma parede. Você pode tentar isso quando os módulos não funcionarem da maneira normal.

1. A maioria dos módulos nRF24L01 + do mercado são falsos. Os baratos que podemos encontrar no Mercado Livre, Ebay e ou Amazon são os piores (não se preocupe, com alguns ajustes podemos fazê-los funcionar)

2. O principal problema é a fonte de alimentação, não seu código. A maioria dos códigos on-line funcionará corretamente. Eu mesmo tenho um código funcional que testei pessoalmente. Avise-me se precisar deles.

3. Preste atenção porque os módulos que são impressos como NRF24L01 + são na verdade Si24Ri (sim, um produto chinês).

4. O clone e os módulos falsos vão consumir mais energia, portanto, não desenvolva seu circuito de energia com base no nRF24L01 + datasheet, porque o Si24Ri terá um alto consumo de corrente em torno de 250mA.

5. Cuidado com ondulações de tensão e picos de corrente, esses módulos são muito sensíveis e podem queimar facilmente. (;

6. Adicionar alguns capacitores (10uF e 0,1uF) em Vcc e Gnd do módulo ajuda a tornar seu fornecimento puro e isso funciona para a maioria dos módulos.

Ainda assim, se você tiver problemas, relate na seção de comentários ou leia isto, ou tire suas dúvidas em nosso fórum.

 

Programação nRF24L01 para Arduino

Foi muito fácil usar esses módulos com o Arduino, devido à biblioteca prontamente disponível criada por maniacbug no GitHub. Clique no link para baixar a biblioteca como uma pasta ZIP e adicione-a ao seu IDE Arduino usando a opção Sketch -> Incluir Biblioteca -> Adicionar biblioteca .ZIP. Depois de adicionar a biblioteca, podemos começar a programar para o projeto. Temos que escrever dois programas, um é para o lado do transmissor e o outro para o lado do receptor. No entanto, como disse anteriormente, cada módulo pode funcionar como um transmissor e receptor. Ambos os programas são fornecidos no final desta página, no código do transmissor a opção do receptor será comentada e no programa do receptor o código do transmissor será comentada. Você pode usá-lo se estiver tentando um projeto no qual o módulo deve funcionar como ambos. O funcionamento do programa é explicado abaixo.

Como todos os programas, começamos incluindo os arquivos de header. Como o nRF usa o protocolo SPI, incluímos o header SPI e também a biblioteca que acabamos de baixar. A biblioteca servo é usada para controlar o servo motor.

#include <SPI.h> 
#include "RF24.h"
#include <Servo.h>

A próxima linha é a linha importante onde instruímos a biblioteca sobre os pinos CE e CS. Em nosso diagrama de circuito, conectamos CE ao pino 7 e CS ao pino 8, então definimos a linha como

RF24 myRadio (7, 8);

Todas as variáveis associadas à biblioteca RF devem ser declaradas como uma estrutura de variável composta. Neste programa, a variável msg é usada para enviar e receber dados do módulo RF.

struct package
{
  int msg;
};
typedef struct package Package;
Package data;

Cada módulo de RF possui um endereço único com o qual pode enviar dados para o respectivo dispositivo. Como temos apenas um par aqui, definimos o endereço como zero no transmissor e no receptor, mas se você tiver vários módulos, poderá definir o ID para qualquer string exclusiva de 6 dígitos.

byte addresses[][6] = {"0"};

Em seguida, dentro da função de configuração vazia, inicializamos o módulo RF e configuramos para trabalhar com banda 115, que é livre de ruído, e também configuramos o módulo para funcionar no modo de consumo mínimo de energia com velocidade mínima de 250Kbps.

void setup()
{
  Serial.begin(9600);
  myRadio.begin();
  myRadio.setChannel(115);               //115 bandas acima dos sinais WIFI
  myRadio.setPALevel(RF24_PA_MIN);       //MIN power low rage
  myRadio.setDataRate( RF24_250KBPS ) ;  //Velocidade mínima
  myservo.attach(6);

  Serial.print("Configuração inicializada");
  delay(500);
}

A função void WriteData() grava os dados passados para ela. Como dito anteriormente, o nRF tem 6 canais diferentes nos quais podemos ler ou gravar dados, aqui usamos 0xF0F0F0F066 como endereço para gravar dados. No lado do receptor, temos que usar o mesmo endereço na função ReadData() para receber os dados que foram gravados.

void WriteData()
{
  myRadio.stopListening();              //Pare de receber e comece a transminar
  myRadio.openWritingPipe(0xF0F0F0F066);//Envia dados neste endereço de 40 bits
  myRadio.write(&data, sizeof(data));
  delay(300);
}

A função void WriteData() lê os dados e os coloca em uma variável. Novamente, de 6 tubos diferentes com os quais podemos ler ou gravar dados, usamos 0xF0F0F0F0AA como endereço para ler dados. Isso significa que o transmissor do outro módulo escreveu algo neste endereço e, portanto, estamos lendo do mesmo.

void ReadData()
{
  myRadio.openReadingPipe(1, 0xF0F0F0F0AA); //Qual tubo ler, endereço de 40 bits
  myRadio.startListening();               //Pare de transmitir e comece a receber
  if ( myRadio.available())
  {
    while (myRadio.available())
    {
      myRadio.read( &data, sizeof(data) );
    }
    Serial.println(data.text);
  }
}

Além dessas linhas, as outras linhas do programa são usadas para ler o POT e convertê-lo de 0 a 180 usando a função de mapa e enviá-lo para o módulo Receptor, onde controlamos o servo de acordo. Não os expliquei linha por linha, pois já aprendemos isso em nosso tutorial de interface servo.

 

Controlando o servo motor usando nRF24L01 sem fio

Quando estiver pronto com o programa, carregue o código do transmissor e do receptor (fornecido abaixo) nas respectivas placas Arduino e ligue-os com a porta USB. Você também pode iniciar o monitor serial de ambas as placas para verificar qual valor está sendo transmitido e o que está sendo recebido. Se tudo estiver funcionando conforme o esperado quando você girar o botão POT no lado do transmissor, o servo do outro lado também deve girar de acordo.

 

Código

Código para a peça do transmissor:

/*Transmitir valor POT por meio de NRF24L01 usando Arduino
 * 
 * Pin Conections
 *  CE - 7
    MISO - 12
    MOSI - 11
    SCK - 13
    CS - 8
    POT-A7
*/

#include <SPI.h>  
#include "RF24.h"

RF24 myRadio (7, 8);

struct package
{
  int msg = 0;
};

byte addresses[][6] = {"0"};

typedef struct package Package;
Package data;

void setup()
{
  Serial.begin(9600);
  myRadio.begin();  
  myRadio.setChannel(115);             //115 bandas acima dos sinais WIFI
  myRadio.setPALevel(RF24_PA_MIN);     //MIN power low rage
  myRadio.setDataRate( RF24_250KBPS ); //Velocidade mínima
  delay(500);
  Serial.print("Configuração inicializada");
}

void loop()
{
  int Read_ADC = analogRead(A7);
  char servo_value = map (Read_ADC, 0, 1024, 0,180);
  if (servo_value>1)
    data.msg = servo_value;
  WriteData();
  delay(50);
  //ReadData(); 
  //delay(200);
}

void WriteData()
{
  myRadio.stopListening();                //Pare de receber e comece a transminar
  myRadio.openWritingPipe( 0xF0F0F0F0AA); //Envia dados neste endereço de 40 bits
  myRadio.write(&data, sizeof(data)); 
  Serial.print("\nEnviado:");
  Serial.println(data.msg);
  delay(300);
}

void ReadData()
{ 
  myRadio.openReadingPipe(1, 0xF0F0F0F066); //Qual tubo ler, endereço de 40 bits
  myRadio.startListening();                 //Pare de transmitir e comece a receber
  if ( myRadio.available()) 
  {
    while (myRadio.available())
    {
      myRadio.read( &data, sizeof(data) );
    }
    Serial.print("\nRecebido:");
    Serial.println(data.msg);
  }
}

Código para parte do receptor:

/*CE - 7
MISO - 12
MOSI - 11
SCK - 13
CS - 8
Recentemente testado com nano
*/

#include <SPI.h>  
#include "RF24.h" 
#include <Servo.h>

Servo myservo;

RF24 myRadio (7, 8); 

struct package
{
  int msg;
};
typedef struct package Package;
Package data;

byte addresses[][6] = {"0"}; 

void setup() 
{
  Serial.begin(9600);
  myRadio.begin(); 
  myRadio.setChannel(115);               //115 bandas acima dos sinais WIFI
  myRadio.setPALevel(RF24_PA_MIN);       //MIN power low rage
  myRadio.setDataRate( RF24_250KBPS ) ;  //Velocidade mínima
  myservo.attach(6);
  
  Serial.print("Configuração inicializada");
  delay(500);
}

int Servo_value;
int Pev_servo_value;

void loop()  
{
  ReadData();
  delay(50);
  
  Pev_servo_value = Servo_value;
  Servo_value = data.msg; 

  while (Pev_servo_value< Servo_value)
  {
    myservo.write(Pev_servo_value);
    Pev_servo_value++;
    delay(2);
  }
  while (Pev_servo_value> Servo_value)
  {
    myservo.write(Pev_servo_value);
    Pev_servo_value--;
    delay(2);
  }

  //data.msg = "nada para enviar";
  //WriteData();
  // delay(50);
}

void ReadData()
{
  myRadio.openReadingPipe(1, 0xF0F0F0F0AA); //Qual tubo ler, endereço de 40 bits
  myRadio.startListening();                 //Pare de transmitir e comece a receber

  if ( myRadio.available()) 
  {
    while (myRadio.available())
    {
      myRadio.read( &data, sizeof(data) );
    }
    Serial.print("\nRecebido:");
    Serial.println(data.msg);
  }
}

void WriteData()
{
  myRadio.stopListening();              //Pare de receber e comece a transminar
  myRadio.openWritingPipe(0xF0F0F0F066);//Envia dados neste endereço de 40 bits
  myRadio.write(&data, sizeof(data)); 
  Serial.print("\nEnviado:");
  Serial.println(data.msg);
  delay(300);
}