Crie uma sala de bate-papo privada usando Arduino, nRF24L01 e Processing

Tempo de leitura: 10 minutes

Criar uma rede local para compartilhar pessoal e dados confidenciais tornou-se quase impossível para um homem comum em nosso mundo moderno. Isso ocorre principalmente porque todos os métodos de bate-papo comuns como Whatsapp, Facebook, Hangout e quase tudo envolve uma conexão com a internet.

E se pudéssemos compartilhar dados sem o meio da Internet?

Não seria legal se você pudesse se comunicar com as pessoas dentro de sua casa ou local de trabalho sem um pacote de rede ou conexão com a Internet?

E se pudéssemos personalizar nossa tela de chat com nossa própria imaginação?

Tudo isso é possível com um microcontrolador e um meio de transmissão sem fio. Esta sala de bate-papo do Arduino usando o projeto nRF24L01 irá guiá-lo na configuração de uma sala de bate-papo de baixo custo em sua área local.

 

Explicação de trabalho:

Basicamente, para fazer isso funcionar, precisaremos de um par de placas Arduino e módulos wireless baratos. Os módulos wireless que usaremos aqui são nRF24L01. A razão para escolher esses módulos é que eles são os sucessores do Zigbee e são fáceis de trabalhar com uma conexão configurada. Além disso, esses módulos funcionam em 2,4 GHz (banda ISM) com espectro de propagação de salto de frequência e opções de burst de choque que nos fazem sentir relaxados em relação a problemas de interferência.

Nosso Arduino e NRF24L01 são conectados para estabelecer uma comunicação serial para que eles possam se comunicar. Os NRF24L01 são módulos transceptores half duplex, portanto podem enviar e receber dados. Os dados são coletados do usuário e transmitidos; esses dados podem ser recebidos por qualquer (ou um determinado) módulo e exibi-los em sua tela.

Mas!!!!! Vamos bater um papo usando a tela de depuração do Arduino? Claro que não. Vamos construir e personalizar nossa própria tela de bate-papo com a ajuda de ‘Processamento’. O Processing é um software capaz de se comunicar com o Arduino usando o UART. Vamos criar um arquivo .exe com linguagem de processamento, que pode rodar em qualquer computador com Java Runtime. Para conversar, basta conectar nosso Arduino e abrir esse arquivo .exe e Booooom !! estamos em nossa própria sala de bate-papo Privatizada totalmente gratuita.

Este projeto está limitado a apenas adicionar dois membros à sala de chat, mas o nRF24L01 tem 6 pipelines e, portanto, pode haver no máximo 6 membros em nossa sala de chat. Esta sala pode funcionar dentro do intervalo de 100 metros, dependendo dos módulos nRF24L01.

Componentes necessários:

  • Arduino (qualquer versão ou modelo) – (2)
  • Módulo transceptor sem fio nRF24L01 +- (2)
  • 3.3 Regulador de tensão – (2). (Não obrigatório)
  • Fios de conexão

Diagrama de circuito:

Arduino Mega com nRF24L01:

Arduino Nano com nRF24L01:

Nosso projeto não envolve nenhuma conexão complexa. Usei um Arduino Mega e um Arduino Nano e suas conexões com nRF24L01 são mostradas acima. Você pode usar qualquer modelo do Arduino.

 

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 que os seguintes pontos podem ajudá-lo a não ser atingido em uma parede.

1. A maioria dos módulos nRF24L01 + do mercado são falsos. Os baratos que podemos encontrar no Ebay e 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 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. (;-( fritou 2 módulos até agora)

6. Adicionar dois capacitores (10uF e 0,1uF) em Vcc e Gnd do módulo ajuda a tornar sua alimentação pura 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.

 

Programando os Arduinos:

O programa para Arduino Nano e Mega será semelhante para a alteração dos pinos CE e CS. Explicarei o programa dividindo-o em pequenos segmentos.

Como o Arduino e o nRF24L01 se comunicam por meio do SPI, chamamos a biblioteca SPI. Também incluímos nossa lib Maniacbug RF24 para que nossos módulos RF funcionem. Baixe o arquivo aqui e adicione-o ao seu IDE.

Programando os Arduinos:

O programa para Arduino Nano e Mega será semelhante para a alteração dos pinos CE e CS. Explicarei o programa dividindo-o em pequenos segmentos.

Como o Arduino e o nRF24L01 se comunicam por meio do SPI, chamamos a biblioteca SPI. Também incluímos nossa lib Maniacbug RF24 para que nossos módulos RF funcionem. Baixe o arquivo aqui e adicione-o ao seu IDE.

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

Nossos módulos NRF são conectados aos pinos 8 e 10 para CE e CS, respectivamente.

RF24 myRadio (8, 10);

Criamos um pacote de dados estruturados chamado pacote. A variável text[20] será usada para transmitir dados no ar.

struct package
{
  char  text[20]; //Text to transmit on air
};
typedef struct package Package;
Package data;

Na função ‘void setup()’, inicializamos a taxa de transmissão para 9600 e configuramos nossos módulos para 115 com consumo mínimo de energia e velocidade de 250KBPS. Você pode brincar com esses valores mais tarde.

void setup() 
{
  Serial.begin(9600);
  delay(1000);
  //Serial.print("Configuração inicializada");
  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
}

O módulo é feito para funcionar no modo de transmissão se os dados forem recebidos através do buffer serial, caso contrário, ele estará no modo receptor procurando por dados no ar. Os dados do usuário são armazenados em um Array char e enviados para WriteData() para transmiti-los.

void loop()  
{
  while(Serial.available()>0) //Get values from user
  { 
    val = Serial.peek();
    if(index < 19) // Um a menos que o tamanho da matriz
    {
       inChar = Serial.read(); // Leia um personagem
       inData[index] = inChar; // Armazene-o
       index++; // Aumente onde escrever a seguir
       inData[index] = '\0'; // Nulo termina a string
    }
    if (val=='#')
    { 
      strcpy( data.text, inData);
      WriteData(); //Coloque o módulo no modo de transmissão
      while (index!=0)
      {
        inData[index] = ' ';
        index--;
      }
    }
  }
  ReadData(); //Colocar o modo de recepção do módulo
}

A função void WriteData() grava os dados no endereço 0xF0F0F0F0AA, este endereço é usado como canal de gravação em outro módulo.

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 ReadData() grava os dados em 0xF0F0F0F066 neste endereço, este endereço é usado como tubo de leitura em outro módulo.

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);
  }
}

É isso, nossa parte de programação acabou. Se você não consegue entender algumas coisas aqui, verifique os dois programas para ambos os Arduinos, fornecidos na seção Código abaixo, adicionei linhas de comentários para explicar as coisas muito melhor.

 

Programa de Processamento:

‘Processing’ é um software de código aberto usado por artistas para design gráfico. Este software é usado para desenvolver software e aplicativos Android. É muito fácil de desenvolver e muito semelhante ao IDE de desenvolvimento Android. Portanto, encurtei a explicação.

O código de processamento para ambas as telas de bate-papo é fornecido aqui:

Codigo 1

import processing.serial.*; // Abrir porta serial

Serial port;

char[] inData = new char[20]; // Alocar algum espaço para a corda
char inChar; // Onde armazenar o caractere lido
byte index = 0; // Índice na matriz; onde armazenar o personagem
int val;

char[] getData = new char[100];
char KeyData;
int charPos=0;

String display;

void setup()
{
  size(510,500);
  port = new Serial(this,Serial.list()[4],9600); // Lê a 4ª PORTA a 9600 baudrate
  println(Serial.list());
  background(0);
}

void draw()
{
  if (port.available()>0) {
     if(index < 19) {
        inChar = char(port.read()); 
        if (inChar == '#')
           inData[index] = ' ';
        else
          inData[index] = inChar; 
        index++; 
        inData[index] = ' ';  
      }
  }
  
  if (inChar == '#')
  {
    // println(str(inData));
    printString();  
    index=0;
    port.clear();
  }
}

void printString()
{
   fill(100);
   rect(0,height/2,width,height/2);
   int x=width/8, y= height -(height/4); 
   for(int j=0; j<20; j++)
   {
     fill(255);
     text(inData[j], x+j*10, y);
   }
}


void keyPressed() {
  int keyIndex = -1;
  if(key== ' ') {
     keyIndex=-33;
  }
   
  if (key >= 'A' && key <= 'Z') {
     keyIndex = key - 'A';
  } else if (key >= 'a' && key <= 'z') {
     keyIndex = key - 'a';
  }
  
  if (keyIndex == -1) 
  {
    // background(0);
    ToprintString();
    clearString();
    charPos=0;  
  } else { 
    //  background(0);
    fill(255);
    KeyData = char(keyIndex+65);
    if(keyIndex!=-1)
    {
      getData[charPos] = KeyData;
      charPos++;
      getData[charPos] = '#';
    }
  }
}

void ToprintString()
{
   fill(100,50,50);
   rect(0,0,width,height/2);
   int x=width/8, y= (height/4);  
   for(int j=0; j<=charPos; j++)
   {
     fill(255);
     if (j!=charPos)
        text(getData[j], x+j*10, y);
     print(getData[j]);
     port.write(getData[j]);
   }
}

void clearString()
{
  for (int reset=0; reset<=charPos; reset++)
     getData[reset] = ' ';
}

 

Código 2

import processing.serial.*;

Serial port;

char[] inData = new char[20]; // Alocar algum espaço para a corda
char inChar; // Onde armazenar o caractere lido
byte index = 0; // Índice na matriz; onde armazenar o personagem
int val;

char[] getData = new char[100];
char KeyData;
int charPos=0;

String display;

void setup()
{
  size(510,500);
  port = new Serial(this,Serial.list()[5],9600);
  println(Serial.list());
  background(0);
}

void draw()
{
    
  if (port.available()>0)
  {
     if(index < 19) 
     {
        inChar = char(port.read()); 
        if (inChar == '#')
           inData[index] = ' ';
        else
          inData[index] = inChar; 
        index++; 
        inData[index] = ' ';    
      }
  }
  
  if (inChar == '#')
  {
    // println(str(inData)); 
    printString();  
    index=0;
    port.clear();
  }
}

void printString()
{
  fill(100);
  rect(0,height/2,width,height/2);
  int x=width/8, y= height -(height/4);  
  for(int j=0; j<20; j++)
  {
    fill(255);
    text(inData[j], x+j*10, y);
  }
}

void keyPressed() {
  int keyIndex = -1;
  
  if(key== ' ')
  {
    keyIndex=-33;
  }
    
  if (key >= 'A' && key <= 'Z') {
    keyIndex = key - 'A';
  } else if (key >= 'a' && key <= 'z') {
    keyIndex = key - 'a';
  }
  
  if (keyIndex == -1) 
  {
    ToprintString();
    clearString();
    charPos=0;  
  } else { 
    fill(255);
    KeyData = char(keyIndex+65);
    if(keyIndex!=-1)
    {
      getData[charPos] = KeyData;
      charPos++;
      getData[charPos] = '#';
    }
  }
}

void ToprintString()
{
   fill(100,50,50);
   rect(0,0,width,height/2);
   int x=width/8, y= (height/4);  
   for(int j=0; j<=charPos; j++)
   {
     fill(255);
     if (j!=charPos)
       text(getData[j], x+j*10, y);
     print(getData[j]);
     port.write(getData[j]);
   }
}

void clearString()
{
  for (int reset=0; reset<=charPos; reset++)
  getData[reset] = ':';
}

Na seção de código a seguir, a “porta = new Serial(this, Serial.list () [4], 9600); // Lê a 4ª PORTA a 9600 baudrate” é importante, pois decide de qual porta os dados serão fornecidos.

void setup()
{
  size(510,500);
  port = new Serial(this,Serial.list()[4],9600); //Lê a 4ª PORTA a 9600 baudrate
  println(Serial.list());
  background(0);
}

Aqui eu li dados da 4ª porta do meu Arduino.

Por exemplo, se você tiver COM[5] COM[2] COM[1] COM[7] COM[19]

Então, o código acima lerá os dados do COM [7].

Agora, como nosso esboço de processamento e Arduino está pronto, basta fazer o upload do programa para o Arduino e deixá-lo conectado ao seu laptop. Abra seu sketch de Processing e comece a digitar e pressione “Enter”, sua mensagem será transmitida para o outro Arduino que exibirá o texto recebido em outro aplicativo de Processing conectado a outro computador. Além disso, verifique o vídeo abaixo para uma demonstração completa.

Então é assim que você pode falar com seus amigos e familiares em sua área local sem ter nenhuma conexão com a Internet, usando esta sala de bate-papo barata do Arduino.

 

Código

Código para Arduino Mega:

/**********
Arduino Mega com NRF24l01 para o projeto Chatroom
***********/

#include <SPI.h>  
#include "RF24.h"  // Manicbug LIB a ser baixado

RF24 myRadio (49, 53); //CE para 49 e 53 para CS
struct package
{
  char  text[20]; //Texto para transmitir no ar
};

//byte addresses[][6] = {"0"}; 
char inData[20]; // Alocar algum espaço para a String
char inChar; // Onde armazenar o caractere lido
byte index = 0; // Índice na matriz; onde armazenar o personagem
 int val;

typedef struct package Package;
Package data;

void setup() 
{
  Serial.begin(9600);
  delay(1000);
  //Serial.print("Configuração inicializada");
  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
}

void loop()  
{
  while(Serial.available()>0) //Obtenha valores do usuário
  { 
    val = Serial.peek();
    if(index < 19) //Um a menos que o tamanho do array
    {
       inChar = Serial.read(); // Leia um personagem
       inData[index] = inChar; // Armazene-o
       index++; // Aumente onde escrever a seguir
       inData[index] = '\0'; // Nulo termina a string
    }
    if (val=='#')
    { 
      strcpy( data.text, inData);
      WriteData(); //Coloque o módulo no modo de transmissão
      while (index!=0)
      {
        inData[index] = ' ';
        index--;
      }
    }
  }
  ReadData(); //Colocar o modo de recepção do módulo
}

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.text);
  }
}

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);
}

Código para Arduino Nano:

/**********
Arduino Nano com NRF24l01 para projeto Chatroom
***********/

#include <SPI.h>  
#include "RF24.h"  // Manicbug LIB a ser baixado

RF24 myRadio (8, 10); // CE to 8 and 10 to CS

struct package
{
  char  text[20]; //Texto para transmitir no ar
};

typedef struct package Package;
Package data;

char inData[20]; // Alocar algum espaço para a String
char inChar; //Onde armazenar o caractere lido
byte index = 0; // Índice na matriz; onde armazenar o personagem
 int val;

void setup()
{
  Serial.begin(9600);
  delay(1000);
  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
  //Serial.print("Setup Initialized");
}

void loop()
{
  while(Serial.available()>0) //Obtenha valores do usuário
  { 
    val = Serial.peek();
    if(index < 19) // Um a menos que o tamanho da matriz
    {
        inChar = Serial.read(); // Leia um personagem
        inData[index] = inChar; // Armazene-o
        index++; // Aumente onde escrever a seguir
        inData[index] = '\0'; // Null terminate the string
    }
    if (val=='#')
    { 
      strcpy( data.text, inData);
      WriteData(); //Coloque o módulo no modo de transmissão
      while (index!=0)
      {
        inData[index] = ' ';
        index--;
      }
    }
  }
  ReadData(); //Colocar o modo de recepção do módulo
}

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.text);
  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.text);
  }
}