Manual
do
Maker
.
com
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.
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.
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:
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.
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.
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.
#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?
#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!
Autor do blog "Do bit Ao Byte / Manual do Maker".
Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.