Manual

do

Maker

.

com

Rádio frequência com Arduino (com strings)

Rádio frequência com Arduino (com strings)

Poderia não ser algo tão simples, mas felizmente alguém desenvolveu uma bela biblioteca para interagir com rádio frequência com Arduino. Por esse motivo inicio o post dizendo claramente; esse é um tutorial nível 1, para qualquer iniciante, mas também um atalho para os experientes.

Esse módulo trabalha  à 433MHz e tem um alcance de até 90 metros em espaço aberto. Sua comunicação é um bocado lenta, podendo variar entre 0 e 9200bps; quanto maior a distância, menor deve ser a velocidade para reduzir a taxa de erros. De qualquer modo, esse não é um dispositivo para interfacear com downloads de sistemas operacionais, além de quê, velocidades de 4200bps são suficientes para diversos tipos de tarefa como por exemplo, abrir portões, acionar relés e tarefas simplistas, na qual se inclui controle remoto para robôs etc.

Se você chegou a esse artigo, sorte minha, porque uma breve pesquisa no google retornará para você muitos outros tutoriais sobre o mesmo assunto, mas eu não poderia deixar de escrever a respeito, uma vez que esse módulo receptor-emissor é extremamente barato e prático de utilizar.

Onde comprar o transmissor-receptor RF

Esse produto você encontra fácil, mas recomendo esse vendedor porque ele tem alguns produtos diferentes como chip de rádio FM, gravador/player para Arduino, chip modulador de voz e outros. Considerando o baixíssimo custo desse conjunto emissor-receptor, vale muito a pena comprar mais alguns brinquedos junto pra compensar o frete. Todos estes que citei (e mais alguns) virarão artigo aqui no site, é só acompanhar.

Biblioteca VirtualWire para rádio frequência com Arduino

No documento do autor da biblioteca ele descreve uma variação de distância que pode chegar a 150m à 1000bps em campo aberto, mas dá pra entender que esse 'campo aberto' deve ser algo como a superfície lunar, porque corpos humanos, objetos e a posição dos módulos influenciam na qualidade de transmissão, portanto, faça seus próprios testes.

Utilizar um fio rígido de cobre como antena aumenta consideravelmente o sinal e é realmente sugerido. Veja na imagem d receptor que um dos 4 pinos é para a antena, mas ela não é obrigatória.

O pino pode ser selecionado pela funçao 'vw_set_*_pin() ' e o wiring é tão simples quanto se possa imaginar. No próprio documento (caprichadíssimo por sinal) você verá estas representações para wiring:

01a.webp
02a.webp

Primeiro passo - baixar e disponibilizar a biblioteca

Nesse link você encontra uma biblioteca excelente para interagir com o dispositivo de rádio frequência com Arduino e acredite, não é uma biblioteca trivial, são mais de 400 linhas de código pra entregar uma interface limpa para o programador da aplicação (nós). Após baixar a biblioteca, siga os passos padrão, descomprimindo-a dentro do diretorio 'libraries' do Arduino. Supondo a IDE 1.6.7 (já antiga na data desse post, mas ainda a utilizo):

cd
cp Downloads/VirtualWire.rar arduino-1.6.7/libraries
cd arduino-1.6.7/libraries
unrar x VirtualWire.rar && rm -f VirtualWire.rar
#no caso da versao zip:
unzip VirtualWire.zip && rm -f VirtualWire.zip

Se você estiver com a IDE do Arduino aberta, feche-a e abra-a novamente para que seja feita a releitura das bibliotecas.

Segundo passo - fazer o wiring

03a.webp

Siga o desenho disposto mais acima. Você pode escolher o pino que quiser, só sugiro que em ambas as controladoras seja utilizado o mesmo pino para reduzir a probabilidade de engano. Atente também ao esquema acima, porque o transmissor está com o VCC silkado no terceiro pino, mas se você reparar no canto, está escrito ATAD (que foi uma cagada ao fazer o silk, porque na verdade é DATA). Portanto, VCC é o pino do meio e à esquerda, DATA.

No receptor, o pino ao lado do VCC é o pino de dados. O primeiro pino após o pino de dados é a antena, você pode colocar até um clip de papel que terá seu efeito como antena, mas para esse teste tão próximo que estou fazendo (para aproveitar o mesmo notebook) sequer necessita antena.

Terceiro passo - codificar

Esse é o passo mais simples porque não tem segredos. Para mostrar a recepção dos dados transmitidos fiz uma brincadeira com LED RGB, enviando a string formatada para o receptor, com um pequeno parsing só pra brincar.

Vou discorrer sobre o código em comentários nele mesmo.

Transmitter

#include <VirtualWire.h>
#define TX_PIN 7

//guardara o resultado final
String rgb;
//so faz a transmissao se houver mensagem da serial
bool go = false;

void setup(){
    //o comum de sempre; inicia a serial a 9600
    Serial.begin(9600);
    vw_set_ptt_inverted(true);
    vw_set_tx_pin(TX_PIN); //pino para transmitir
    vw_setup(2000);// velocidade ate 9000
}

void loop(){
    if (Serial.available() >0){
      //parsing pra validar
      int red = Serial.parseInt();
      int green = Serial.parseInt();
      int blue = Serial.parseInt();

      if (Serial.read() == '\n') {
          //garante o limite minimo e maximo
          red   = constrain(red, 0, 255);
          green = constrain(green, 0, 255);
          blue  = constrain(blue, 0, 255);
      }
      //Recompoe a string, agora garantindo o formato
      char RED[4],GREEN[4],BLUE[4];
      sprintf(RED,"%03d",red);
      sprintf(GREEN,"%03d",green);
      sprintf(BLUE,"%03d",blue);

      rgb =  String(RED) + "," + String(GREEN) + "," + String(BLUE);
      go = true;
    }

    if (go){
        char result[27];
        rgb.toCharArray(result,rgb.length()+1);
    
        Serial.println(result);
        vw_send((uint8_t *)result, strlen(result));
        vw_wait_tx(); //aguarda 'passar pela garganta'
        go = false;
    }
}

Como você pode notar, o único cuidado que tomei foi de não interromper o fluxo mas também não ficar executando nada à toa. De resto, é um processo muito básico. Em relação ao formato da mensagem, só fiz questão de garantir o formato antes do envio, afinal, é mais fácil garantir o formato antes de sair do que fazer parsing no destino em busca de erros, certo?

Receiver

#include <VirtualWire.h>
#define RX_PIN 7

//pinos PWM do LED RGB
#define R 3
#define G 5
#define B 6

//essa estrutura tem o proposito de economizar. Se tiver duvidas,
//leia:
//http://www.manualdomaker.com/article/programar-em-cc-para-microcontroladoras-pic-e-arduino/

struct devices
{
    int d        : 3;
    int j        : 3;
    int RGB[3] = {0};
    int     times[3];
};

struct devices valuesRGB;

void setup(){
    //coloca os pinos do RGB em OUTPUT 
    pinMode(R,OUTPUT);
    pinMode(G,OUTPUT);
    pinMode(B,OUTPUT);

    /comeca em branco
    digitalWrite(R,255);
    digitalWrite(G,255);
    digitalWrite(B,255);
    
    //multiplicador
    valuesRGB.times[0] = 100;
    valuesRGB.times[1] = 10;
    valuesRGB.times[2] = 1;
    
    //configuracao e inicializacao do receptor
    vw_set_ptt_inverted(true);
    vw_set_rx_pin(RX_PIN);
    vw_setup(2000);  //velocidade compativel com o emitter
    vw_rx_start();       //inicio da recepcao
    //serial para debug
    Serial.begin(9600);
}

//nao esta em uso, mas sempre crio pra limpar array de char
void clear(char *var){
  for (int k=0;k<strlen(var);k++){
      var[k] = 0;
  }
}

//recebe o array e aplica os valores ao LED
void changeLEDcollor(int* rgb){
    analogWrite(R,rgb[0]);
    analogWrite(G,rgb[1]);
    analogWrite(B,rgb[2]);
}

//conversao para RGB
void toRGB(uint8_t *msg, uint8_t msgLen){
    int i = 0;
    valuesRGB.j = 0;
    valuesRGB.d = 0;
    valuesRGB.RGB[0] = valuesRGB.RGB[1] = valuesRGB.RGB[2] = 0;
    for (int i=0;i<msgLen;i++){
        if (i == 3 || i == 7){
            i++;
            Serial.println(valuesRGB.RGB[0]);
            Serial.println(valuesRGB.RGB[1]);
            Serial.println(valuesRGB.RGB[2]);
            valuesRGB.d=0;
            valuesRGB.j++;
        }

        valuesRGB.RGB[valuesRGB.j] += (msg[i]-48) * valuesRGB.times[valuesRGB.d];
        valuesRGB.d++;
    }
}

void loop(){
    //Le e determina os limites
    uint8_t buf[VW_MAX_MESSAGE_LEN];
    uint8_t buflen = VW_MAX_MESSAGE_LEN;

    if (vw_get_message(buf, &buflen)){
        if (buf[0] == '-'){
            valuesRGB.RGB[0] = 0;
            valuesRGB.RGB[1] = 0;
            valuesRGB.RGB[2] = 0;
            changeLEDcollor(valuesRGB.RGB);
        }
        else{
            toRGB(buf,buflen);
            changeLEDcollor(valuesRGB.RGB);
        }
    }
}

Simples também, hum? Gosto de fazer testes assim, é bem divertido escrever código pra teste.

O video só mostra o LED RGB mudando de cor conforme mando o comando, só pra mostrar esse código funcionando, nem recomendo o video, mas aí está.

https://www.youtube.com/watch?v=tuUXTM--bkE

Inscreva-se no nosso canal Manual do Maker Brasil no YouTube.

Próximo post a caminho!

Nome do Autor

Djames Suhanko

Autor do blog "Do bit Ao Byte / Manual do Maker".

Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.