Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Manufacturing Technology >> Processo de manufatura

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

Neste tutorial, vamos aprender a construir um transmissor RC Arduino DIY. Frequentemente preciso de controle sem fio para meus projetos, por isso construí este controlador de rádio multifuncional que pode ser usado para praticamente qualquer coisa.

Você pode assistir ao vídeo a seguir ou ler o tutorial escrito abaixo.

Visão Geral

Agora posso controlar sem fio qualquer projeto Arduino com apenas alguns pequenos ajustes no lado do receptor. Este transmissor também pode ser usado como qualquer controlador RC comercial para controlar brinquedos RC, carros, drones e assim por diante. Para isso, basta um receptor Arduino simples que gere os sinais apropriados para controlar esses dispositivos RC comerciais.

Explicarei como tudo funciona através de alguns exemplos: controle de um carro robô Arduino, controle do Robô Formiga Arduino do meu vídeo anterior e controle de um motor DC brushless usando um ESC e alguns servomotores.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

A comunicação de rádio deste controlador é baseada no módulo transceptor NRF24L01, que, se usado com uma antena amplificada, pode ter um alcance estável de até 700 metros em espaço aberto. Ele possui 14 canais, dos quais 6 são entradas analógicas e 8 são entradas digitais.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

Possui dois joysticks, dois potenciômetros, duas chaves seletoras, seis botões e, adicionalmente, uma unidade de medição interna composta por um acelerômetro e um giroscópio, que também pode ser usada para controlar coisas apenas movendo ou inclinando o controlador.

Diagrama de Circuito do Transmissor RC Arduino

Para começar, vamos analisar o diagrama de circuito. O cérebro deste controlador RC é um Arduino Pro Mini, alimentado por duas baterias LiPo que produzem cerca de 7,4 volts. Podemos conectá-las diretamente ao pino RAW do Pro Mini, que possui um regulador de tensão que reduz a voltagem para 5V. Note que existem duas versões do Arduino Pro Mini: uma que opera a 5V e outra a 3,3V.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

Por outro lado, o módulo NRF24L01 exige estritamente 3,3V e é recomendável que venha de uma fonte dedicada. Portanto, precisamos usar um regulador de tensão de 3,3V conectado às baterias para converter 7,4V em 3,3V. Também precisamos usar um capacitor de desacoplamento bem próximo ao módulo para manter a tensão mais estável, tornando a comunicação de rádio mais estável também. O módulo NRF24L01 comunica-se com o Arduino usando protocolo SPI, enquanto o módulo acelerômetro e giroscópio MPU6050 usa o protocolo I2C.

Você pode obter os componentes necessários para este tutorial Arduino nos links abaixo:

Design da PCB

Acabei utilizando todos os pinos analógicos e digitais do Arduino Pro Mini. Se tentasse conectar tudo usando jumpers, seria uma bagunça. Por isso, projetei uma PCB personalizada usando o software gratuito de design de circuitos online EasyEDA.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

Aqui levei em consideração a ergonomia do controlador e o projetei para ser facilmente segurado com as duas mãos, enquanto todos os controles ficam ao alcance dos dedos. Arredondei as bordas e adicionei furos de 3mm para poder fixar a PCB em algo posteriormente. Posicionei os pinos para programação do Arduino Pro Mini no lado superior do controlador para fácil acesso caso queiramos reprogramar o Arduino. Também podemos notar que usei os pinos RX e TX do Arduino para os botões dos joysticks. No entanto, estas duas linhas precisam ser desconectadas de qualquer coisa enquanto enviamos o sketch para o Arduino. Por isso, são interrompidas com dois pinos que podem ser facilmente conectados usando jumpers simples.

Observação importante: Certifique-se de ter a versão correta do Arduino Pro Mini para combinar com a PCB ou modifique o design da PCB de acordo. Aqui está uma foto comparativa entre as três versões diferentes, dependendo do seu Arduino e do regulador de tensão.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

Aqui está o link para os arquivos do projeto deste design de PCB. Eles abrem as três versões diferentes em abas separadas, para que você possa escolher a que precisa.

Uma vez finalizado o design, gerei o arquivo Gerber necessário para a fabricação da PCB.

Arquivo Gerber:

Então, encomendei a PCB na JLCPCB, que também são os patrocinadores deste vídeo.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

Aqui podemos simplesmente arrastar e soltar o arquivo Gerber e, uma vez carregado, podemos revisar nossa PCB no visualizador Gerber. Se tudo estiver correto, podemos prosseguir e selecionar as propriedades desejadas para nossa PCB. Desta vez, escolhi a cor preta. E pronto, agora podemos simplesmente encomendar nossa PCB a um preço razoável. Note que se for seu primeiro pedido na JLCPCB, você pode obter até 10 PCBs por apenas $2.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

E aqui está. Adorei como esta PCB ficou na cor preta. A qualidade é excelente e tudo corresponde exatamente ao design.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

Montagem da PCB

Ok, agora podemos prosseguir com a montagem da PCB. Comecei soldando os headers de pinos do Arduino Pro Mini. Uma maneira fácil e boa de fazer isso é colocá-los em uma protoboard para que fiquem firmes no lugar durante a soldagem.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

O Pro Mini também tem pinos nas laterais, mas note que a localização destes pinos pode variar dependendo do fabricante.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

Para o modelo específico que tenho, preciso de 5 pinos para cada lado, deixando um pino GND vazio porque usei a área abaixo dele na PCB para passar alguns trilhos. Soldei o Arduino Pro Mini diretamente na PCB e cortei o excesso dos headers. Ao lado dele vai o módulo acelerômetro e giroscópio MPU6050.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

Depois, soldei o regulador de tensão 3.3V com um capacitor ao lado, e outro capacitor próximo ao módulo NRF24L01. Este módulo tem três versões diferentes e podemos usar qualquer uma delas aqui.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

Continuei com os pinos para programação do Arduino, os pinos RX e TX, os pinos de alimentação e o interruptor de energia.

Para soldar os potenciômetros na PCB, precisei estender seus pinos usando alguns headers de pinos.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

Podemos notar que cortei anteriormente o comprimento dos botões para poder encaixar alguns caps neles. No entanto, soldaremos os potenciômetros na PCB um pouco mais tarde.

Então, inseri e soldei as duas chaves seletoras e os dois joysticks no lugar.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

Finalmente, o que resta é soldar os quatro botões de pressão. No entanto, eles não têm a altura adequada, então usei novamente headers de pinos para estender seus pinos um pouco.

E pronto, nossa PCB está pronta para continuarmos com a fabricação da capa. Como gosto de como a PCB fica e quero que seja visível, decidi usar acrílico transparente para a capa.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

Aqui tenho acrílico transparente de 4mm de espessura, que atualmente tem uma película protetora e parece azul. A ideia para a capa é fazer duas placas com o formato da PCB e fixar uma no lado superior e a outra no lado inferior da PCB.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo
Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

Marquei o formato da PCB e, usando uma serra manual para metal, cortei o acrílico de acordo.

Depois, usando uma lixa simples, ajustei finamente o formato do acrílico. As duas placas ficaram ótimas e combinam perfeitamente com a PCB.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

Em seguida, marquei os locais onde preciso fazer aberturas para os componentes passarem. Usando uma broca de 3mm, fiz primeiro os 4 furos para fixar as placas na PCB. Para estes furos, também fiz contra-afundamentos para que os parafusos fiquem nivelados com as placas.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

Para as aberturas das chaves seletoras e potenciômetros usei broca de 6mm, e para as aberturas dos joysticks usei uma broca Forstner de 25mm. Novamente, usando uma lixa, ajustei finamente todas as aberturas.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

Antes de montar a capa, uma observação rápida: soldei o header de pinos da fonte de alimentação de cabeça para baixo para que possa ser acessado pelo lado de trás, onde a bateria ficará localizada.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

Ok, agora podemos começar a montar a capa. Comecei removendo a película protetora do acrílico, o que devo admitir foi bastante satisfatório porque o acrílico ficou tão limpo. Primeiro, fixei os dois potenciômetros na placa superior, inseri os parafusos de fixação de 3mm e coloquei os espaçadores de 11mm no lugar.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

Então, uni e fixei cuidadosamente a placa superior e a PCB usando alguns parafusos. Neste ponto, finalmente soldei os potenciômetros na PCB porque antes não sabia exatamente em que altura eles ficariam posicionados.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

Na placa traseira, fixei o suporte da bateria usando 2 parafusos. Finalizei a montagem da capa fixando a placa traseira no lado de trás da PCB usando os quatro parafusos de fixação.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

Finalmente, podemos conectar os fios da bateria aos pinos de alimentação, inserir e fixar os botões nos potenciômetros, inserir os caps dos joysticks e conectar a antena ao módulo NRF24L01. E pronto, terminamos o transmissor RC Arduino DIY.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

O que resta agora é programar o Arduino. Para programar uma placa Pro Mini, precisamos de uma interface USB para serial UART que pode ser conectada ao header de programação localizado no lado superior do nosso controlador.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

Então, no menu Ferramentas da IDE Arduino, precisamos selecionar a placa Arduino Pro ou Pro Mini, selecionar a versão correta do processador, selecionar a porta e selecionar o método de programação como "USBasp".

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

E assim podemos carregar o código para o Arduino.

Código do Transmissor RC Arduino DIY

Vamos explicar como funciona o código do transmissor. Primeiro, precisamos incluir as bibliotecas SPI e RF24 para comunicação sem fio, e a biblioteca I2C para o módulo acelerômetro. Depois, definimos as entradas digitais, algumas variáveis necessárias para o programa, definimos o objeto de rádio e o endereço de comunicação.

#include <SPI.h> 
#include <nRF24L01.h> 
#include <RF24.h> 
#include <Wire.h> 
// Define as entradas digitais
#define jB1 1 // Botão do joystick 1
#define jB2 0 // Botão do joystick 2
#define t1 7  // Chave seletora 1
#define t2 4  // Chave seletora 2
#define b1 8  // Botão 1
#define b2 9  // Botão 2
#define b3 2  // Botão 3
#define b4 3  // Botão 4
const int MPU = 0x68; // Endereço I2C do MPU6050
float AccX, AccY, AccZ;
float GyroX, GyroY, GyroZ;
float accAngleX, accAngleY, gyroAngleX, gyroAngleY;
float angleX, angleY;
float AccErrorX, AccErrorY, GyroErrorX, GyroErrorY;
float elapsedTime, currentTime, previousTime;
int c = 0;
RF24 radio(5, 6); // nRF24L01 (CE, CSN)
const byte address[6] = "00001"; // Endereço

Em seguida, precisamos definir uma estrutura onde armazenaremos os 14 valores de entrada do controlador. O tamanho máximo desta estrutura pode ser 32 bytes porque esse é o limite do buffer do NRF24L01 ou a quantidade de dados que o módulo pode enviar de uma vez.

// Tamanho máximo desta struct é 32 bytes - limite do buffer NRF24L01
struct Data_Package {
  byte j1PotX;
  byte j1PotY;
  byte j1Button;
  byte j2PotX;
  byte j2PotY;
  byte j2Button;
  byte pot1;
  byte pot2;
  byte tSwitch1;
  byte tSwitch2;
  byte button1;
  byte button2;
  byte button3;
  byte button4;
};
Data_Package data; // Cria uma variável com a estrutura acima

Na seção setup, precisamos inicializar o módulo MPU6050 e também podemos calcular o erro do IMU, que é um valor usado posteriormente ao calcular os ângulos corretos do módulo.

void initialize_MPU6050() {
  Wire.begin(); // Inicializa comunicação
  Wire.beginTransmission(MPU); // Inicia comunicação com MPU6050
  Wire.write(0x6B); // Fala com o registrador 6B
  Wire.write(0x00); // Faz reset - coloca 0 no registrador 6B
  Wire.endTransmission(true); // fim da transmissão
  // Configura Acelerômetro
  Wire.beginTransmission(MPU);
  Wire.write(0x1C); // Fala com o registrador ACCEL_CONFIG
  Wire.write(0x10); // Define bits do registrador como 00010000 (+/- 8g escala total)
  Wire.endTransmission(true);
  // Configura Giroscópio
  Wire.beginTransmission(MPU);
  Wire.write(0x1B); // Fala com o registrador GYRO_CONFIG (1B hex)
  Wire.write(0x10); // Define bits do registrador como 00010000 (1000dps escala total)
  Wire.endTransmission(true);
}

Você pode encontrar mais detalhes sobre como funcionam acelerômetro e giroscópio MEMS aqui. Um tutorial dedicado ao MPU6050 chegará em breve.

Em seguida, precisamos inicializar a comunicação de rádio, ativar os resistores pull-up internos do Arduino para todas as entradas digitais e definir os valores iniciais padrão para todas as variáveis.

// Define a comunicação de rádio
radio.begin();
radio.openWritingPipe(address);
radio.setAutoAck(false);
radio.setDataRate(RF24_250KBPS);
radio.setPALevel(RF24_PA_LOW);
// Ativa os resistores pull-up internos do Arduino
pinMode(jB1, INPUT_PULLUP);
pinMode(jB2, INPUT_PULLUP);
pinMode(t1, INPUT_PULLUP);
pinMode(t2, INPUT_PULLUP);
pinMode(b1, INPUT_PULLUP);
pinMode(b2, INPUT_PULLUP);
pinMode(b3, INPUT_PULLUP);
pinMode(b4, INPUT_PULLUP);

Na seção loop, começamos lendo todas as entradas analógicas, mapeando seus valores de 0 a 1023 para valores de byte de 0 a 255, porque já definimos as variáveis em nossa estrutura como bytes. Cada entrada é armazenada na variável de dados correspondente da estrutura.

// Lê todas as entradas analógicas e mapeia para um valor de Byte
data.j1PotX = map(analogRead(A1), 0, 1023, 0, 255); // Converte leitura analógica de 0-1023 para valor BYTE 0-255
data.j1PotY = map(analogRead(A0), 0, 1023, 0, 255);
data.j2PotX = map(analogRead(A2), 0, 1023, 0, 255);
data.j2PotY = map(analogRead(A3), 0, 1023, 0, 255);
data.pot1 = map(analogRead(A7), 0, 1023, 0, 255);
data.pot2 = map(analogRead(A6), 0, 1023, 0, 255);

Devemos notar que, como usamos resistores pull-up, as leituras dos pinos digitais são 0 quando os botões são pressionados.

// Lê todas as entradas digitais
data.j1Button = digitalRead(jB1);
data.j2Button = digitalRead(jB2);
data.tSwitch2 = digitalRead(t2);
data.button1 = digitalRead(b1);
data.button2 = digitalRead(b2);
data.button3 = digitalRead(b3);
data.button4 = digitalRead(b4);

Usando a função radio.write(), simplesmente enviamos os valores de todos os 14 canais para o receptor.

// Envia todos os dados da estrutura para o receptor
radio.write(&data, sizeof(Data_Package));

Caso a chave seletora 1 esteja ligada, usamos os dados do acelerômetro e giroscópio para o controle.

if (digitalRead(t1) == 0) {
  read_IMU(); // Usa MPU6050 em vez do Joystick 1 para controlar movimentos esquerda, direita, frente e trás
}

Assim, em vez dos valores X e Y do joystick 1, usamos os valores de ângulo que obtemos do IMU, que convertemos anteriormente de valores de -90 a +90 graus em valores de byte de 0 a 255 apropriadamente.

// Mapeia valores de ângulo de -90deg a +90deg para valores de 0 a 255, como os valores do Joystick
data.j1PotX = map(angleX, -90, +90, 255, 0);
data.j1PotY = map(angleY, -90, +90, 0, 255);

É assim que funciona o código do transmissor, sendo as partes mais importantes a definição da comunicação de rádio e o envio dos dados para o receptor.

Aqui está o código Arduino completo para este Transmissor RC Arduino DIY:

/* Transmissor RC Baseado em Arduino DIY por Dejan Nedelkovski, www.HowToMechatronics.com
Biblioteca: TMRh20/RF24, https://github.com/tmrh20/RF24/ */
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Wire.h>
// Define as entradas digitais
#define jB1 1 // Botão do joystick 1
#define jB2 0 // Botão do joystick 2
#define t1 7  // Chave seletora 1
#define t2 4  // Chave seletora 2
#define b1 8  // Botão 1
#define b2 9  // Botão 2
#define b3 2  // Botão 3
#define b4 3  // Botão 4
const int MPU = 0x68; // Endereço I2C do MPU6050
float AccX, AccY, AccZ;
float GyroX, GyroY, GyroZ;
float accAngleX, accAngleY, gyroAngleX, gyroAngleY;
float angleX, angleY;
float AccErrorX, AccErrorY, GyroErrorX, GyroErrorY;
float elapsedTime, currentTime, previousTime;
int c = 0;
RF24 radio(5, 6); // nRF24L01 (CE, CSN)
const byte address[6] = "00001"; // Endereço
// Tamanho máximo desta struct é 32 bytes - limite do buffer NRF24L01
struct Data_Package {
  byte j1PotX;
  byte j1PotY;
  byte j1Button;
  byte j2PotX;
  byte j2PotY;
  byte j2Button;
  byte pot1;
  byte pot2;
  byte tSwitch1;
  byte tSwitch2;
  byte button1;
  byte button2;
  byte button3;
  byte button4;
};
Data_Package data; // Cria uma variável com a estrutura acima
void setup() {
  Serial.begin(9600);
  // Inicializa interface com o MPU6050
  initialize_MPU6050();
  // Chame esta função se precisar obter os valores de erro do IMU para seu módulo
  // calculate_IMU_error();
  // Define a comunicação de rádio
  radio.begin();
  radio.openWritingPipe(address);
  radio.setAutoAck(false);
  radio.setDataRate(RF24_250KBPS);
  radio.setPALevel(RF24_PA_LOW);
  // Ativa os resistores pull-up internos do Arduino
  pinMode(jB1, INPUT_PULLUP);
  pinMode(jB2, INPUT_PULLUP);
  pinMode(t1, INPUT_PULLUP);
  pinMode(t2, INPUT_PULLUP);
  pinMode(b1, INPUT_PULLUP);
  pinMode(b2, INPUT_PULLUP);
  pinMode(b3, INPUT_PULLUP);
  pinMode(b4, INPUT_PULLUP);
  // Define valores iniciais padrão
  data.j1PotX = 127; // Valores de 0 a 255. Quando o Joystick está em repouso, o valor está no meio, ou 127. Mapeamos o valor do pot de 0-1023 para 0-255 porque é um valor BYTE
  data.j1PotY = 127;
  data.j2PotX = 127;
  data.j2PotY = 127;
  data.j1Button = 1;
  data.j2Button = 1;
  data.pot1 = 1;
  data.pot2 = 1;
  data.tSwitch1 = 1;
  data.tSwitch2 = 1;
  data.button1 = 1;
  data.button2 = 1;
  data.button3 = 1;
  data.button4 = 1;
}
void loop() {
  // Lê todas as entradas analógicas e mapeia para um valor de Byte
  data.j1PotX = map(analogRead(A1), 0, 1023, 0, 255);
  data.j1PotY = map(analogRead(A0), 0, 1023, 0, 255);
  data.j2PotX = map(analogRead(A2), 0, 1023, 0, 255);
  data.j2PotY = map(analogRead(A3), 0, 1023, 0, 255);
  data.pot1 = map(analogRead(A7), 0, 1023, 0, 255);
  data.pot2 = map(analogRead(A6), 0, 1023, 0, 255);
  // Lê todas as entradas digitais
  data.j1Button = digitalRead(jB1);
  data.j2Button = digitalRead(jB2);
  data.tSwitch2 = digitalRead(t2);
  data.button1 = digitalRead(b1);
  data.button2 = digitalRead(b2);
  data.button3 = digitalRead(b3);
  data.button4 = digitalRead(b4);
  // Se a chave seletora 1 estiver ligada
  if (digitalRead(t1) == 0) {
    read_IMU(); // Usa MPU6050 em vez do Joystick 1 para controlar movimentos
  }
  // Envia todos os dados da estrutura para o receptor
  radio.write(&data, sizeof(Data_Package));
}
void initialize_MPU6050() {
  Wire.begin();
  Wire.beginTransmission(MPU);
  Wire.write(0x6B);
  Wire.write(0x00);
  Wire.endTransmission(true);
  Wire.beginTransmission(MPU);
  Wire.write(0x1C);
  Wire.write(0x10);
  Wire.endTransmission(true);
  Wire.beginTransmission(MPU);
  Wire.write(0x1B);
  Wire.write(0x10);
  Wire.endTransmission(true);
}
void calculate_IMU_error() {
  while (c < 200) {
    Wire.beginTransmission(MPU);
    Wire.write(0x3B);
    Wire.endTransmission(false);
    Wire.requestFrom(MPU, 6, true);
    AccX = (Wire.read() << 8 | Wire.read()) / 4096.0;
    AccY = (Wire.read() << 8 | Wire.read()) / 4096.0;
    AccZ = (Wire.read() << 8 | Wire.read()) / 4096.0;
    AccErrorX = AccErrorX + ((atan((AccY) / sqrt(pow((AccX), 2) + pow((AccZ), 2))) * 180 / PI));
    AccErrorY = AccErrorY + ((atan(-1 * (AccX) / sqrt(pow((AccY), 2) + pow((AccZ), 2))) * 180 / PI));
    c++;
  }
  AccErrorX = AccErrorX / 200;
  AccErrorY = AccErrorY / 200;
  c = 0;
  while (c < 200) {
    Wire.beginTransmission(MPU);
    Wire.write(0x43);
    Wire.endTransmission(false);
    Wire.requestFrom(MPU, 4, true);
    GyroX = Wire.read() << 8 | Wire.read();
    GyroY = Wire.read() << 8 | Wire.read();
    GyroErrorX = GyroErrorX + (GyroX / 32.8);
    GyroErrorY = GyroErrorY + (GyroY / 32.8);
    c++;
  }
  GyroErrorX = GyroErrorX / 200;
  GyroErrorY = GyroErrorY / 200;
  Serial.print("AccErrorX: "); Serial.println(AccErrorX);
  Serial.print("AccErrorY: "); Serial.println(AccErrorY);
  Serial.print("GyroErrorX: "); Serial.println(GyroErrorX);
  Serial.print("GyroErrorY: "); Serial.println(GyroErrorY);
}
void read_IMU() {
  Wire.beginTransmission(MPU);
  Wire.write(0x3B);
  Wire.endTransmission(false);
  Wire.requestFrom(MPU, 6, true);
  AccX = (Wire.read() << 8 | Wire.read()) / 4096.0;
  AccY = (Wire.read() << 8 | Wire.read()) / 4096.0;
  AccZ = (Wire.read() << 8 | Wire.read()) / 4096.0;
  accAngleX = (atan(AccY / sqrt(pow(AccX, 2) + pow(AccZ, 2))) * 180 / PI) + 1.15;
  accAngleY = (atan(-1 * AccX / sqrt(pow(AccY, 2) + pow(AccZ, 2))) * 180 / PI) - 0.52;
  previousTime = currentTime;
  currentTime = millis();
  elapsedTime = (currentTime - previousTime) / 1000;
  Wire.beginTransmission(MPU);
  Wire.write(0x43);
  Wire.endTransmission(false);
  Wire.requestFrom(MPU, 4, true);
  GyroX = (Wire.read() << 8 | Wire.read()) / 32.8;
  GyroY = (Wire.read() << 8 | Wire.read()) / 32.8;
  GyroX = GyroX + 1.85;
  GyroY = GyroY - 0.15;
  gyroAngleX = GyroX * elapsedTime;
  gyroAngleY = GyroY * elapsedTime;
  angleX = 0.98 * (angleX + gyroAngleX) + 0.02 * accAngleX;
  angleY = 0.98 * (angleY + gyroAngleY) + 0.02 * accAngleY;
  data.j1PotX = map(angleX, -90, +90, 255, 0);
  data.j1PotY = map(angleY, -90, +90, 0, 255);
}

Código do Receptor

Agora vamos ver como podemos receber esses dados. Aqui está um esquema simples de receptor Arduino e NRF24L01. Claro que você pode usar qualquer outra placa Arduino.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

E aqui está um código simples de receptor onde receberemos os dados e simplesmente os imprimiremos no monitor serial para sabermos que a comunicação funciona corretamente. Novamente, precisamos incluir a biblioteca RF24 e definir os objetos e a estrutura da mesma forma que no código do transmissor. Na seção setup, ao definir a comunicação de rádio, precisamos usar as mesmas configurações do transmissor e definir o módulo como receptor usando a função radio.startListening().

/* Projeto Transmissor RC Baseado em Arduino DIY == Código do Receptor ==
por Dejan Nedelkovski, www.HowToMechatronics.com
Biblioteca: TMRh20/RF24, https://github.com/tmrh20/RF24/ */
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(10, 9); // nRF24L01 (CE, CSN)
const byte address[6] = "00001";
unsigned long lastReceiveTime = 0;
unsigned long currentTime = 0;
// Tamanho máximo desta struct é 32 bytes - limite do buffer NRF24L01
struct Data_Package {
  byte j1PotX;
  byte j1PotY;
  byte j1Button;
  byte j2PotX;
  byte j2PotY;
  byte j2Button;
  byte pot1;
  byte pot2;
  byte tSwitch1;
  byte tSwitch2;
  byte button1;
  byte button2;
  byte button3;
  byte button4;
};
Data_Package data; // Cria uma variável com a estrutura acima
void setup() {
  Serial.begin(9600);
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setAutoAck(false);
  radio.setDataRate(RF24_250KBPS);
  radio.setPALevel(RF24_PA_LOW);
  radio.startListening(); // Define o módulo como receptor
  resetData();
}
void loop() {
  // Verifica se há dados para receber
  if (radio.available()) {
    radio.read(&data, sizeof(Data_Package)); // Lê todos os dados e armazena na estrutura 'data'
    lastReceiveTime = millis(); // Neste momento recebemos os dados
  }
  // Verifica se continuamos recebendo dados, ou se temos conexão entre os dois módulos
  currentTime = millis();
  if (currentTime - lastReceiveTime > 1000) {
    // Se o tempo atual for mais de 1 segundo desde que recebemos os últimos dados, significa que perdemos a conexão
    resetData(); // Se a conexão for perdida, reseta os dados. Evita comportamento indesejado, por exemplo, se um drone tem throttle up e perdemos conexão, ele pode continuar voando a menos que resetemos os valores
  }
  // Imprime os dados no Monitor Serial
  Serial.print("j1PotX: "); Serial.print(data.j1PotX);
  Serial.print("; j1PotY: "); Serial.print(data.j1PotY);
  Serial.print("; button1: "); Serial.print(data.button1);
  Serial.print("; j2PotX: "); Serial.println(data.j2PotX);
}
void resetData() {
  // Reseta os valores quando não há conexão de rádio - Define valores iniciais padrão
  data.j1PotX = 127;
  data.j1PotY = 127;
  data.j2PotX = 127;
  data.j2PotY = 127;
  data.j1Button = 1;
  data.j2Button = 1;
  data.pot1 = 1;
  data.pot2 = 1;
  data.tSwitch1 = 1;
  data.tSwitch2 = 1;
  data.button1 = 1;
  data.button2 = 1;
  data.button3 = 1;
  data.button4 = 1;
}

No loop principal, usando a função available(), verificamos se há dados de entrada. Se verdadeiro, simplesmente lemos os dados e armazenamos nas variáveis da estrutura. Agora podemos imprimir os dados no monitor serial para verificar se a transmissão funciona corretamente. Também usando a função millis() e uma instrução if, verificamos se continuamos recebendo dados, ou se não recebemos dados por um período superior a 1 segundo, então resetamos as variáveis para seus valores padrão. Usamos isso para evitar comportamento indesejado, por exemplo, se um drone tem throttle up e perdemos conexão, ele pode continuar voando a menos que resetemos os valores.

Pronto. Agora podemos implementar este método de recepção de dados para qualquer projeto Arduino. Por exemplo, aqui está o código para controlar o carro robô Arduino de um dos meus vídeos anteriores.

Como atualização deste projeto, fiz um Receptor RC dedicado baseado em Arduino. Novamente, é baseado na placa Arduino Pro Mini e tem várias conexões prontas para servos e ESCs, colocadas em uma PCB compacta.

Controle Sem Fio de Carro Robô Arduino usando Transmissor RC

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

Código Arduino:

Aqui precisamos definir as bibliotecas, a estrutura e a comunicação de rádio como explicado anteriormente. Então, no loop principal, apenas precisamos ler os dados de entrada e usar qualquer um deles para o que quisermos. Neste caso, uso os valores do joystick 1 para dirigir o carro.

Controle do Robô Formiga / Hexapod Arduino usando Transmissor RC Arduino

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

Código Arduino:

Da mesma forma, fiz o Robô Formiga Arduino do meu vídeo anterior ser controlado sem fio usando este Transmissor RC Arduino. Precisamos apenas ler os dados e, de acordo com eles, executar as funções apropriadas, como mover para frente, esquerda, direita, morder, atacar e assim por diante.

Controle de ESC e Servo usando Transmissor RC

Por fim, vamos ver como este transmissor pode ser usado para controlar dispositivos RC comerciais.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo

Geralmente, para esses dispositivos, precisamos controlar seus servos ou motores brushless. Então, após receber os dados do transmissor, para controlar servo simplesmente usamos a biblioteca Servo do Arduino e valores de 0 a 180 graus. Para controlar motor brushless usando ESC, podemos novamente usar a biblioteca servo para gerar o sinal PWM de 50Hz usado para controlar o ESC. Variando o ciclo de trabalho de 1000 a 2000 microssegundos, controlamos o RPM do motor de zero ao máximo. Porém, mais sobre controle de motores brushless usando ESC no meu próximo tutorial.

Observe que na verdade não podemos vincular o sistema de receptor RC padrão com este sistema NRF24L01 de 2.4GHz. Em vez disso, precisamos modificar ou criar nosso próprio receptor consistindo de um Arduino e módulo NRF24L01. A partir daí, podemos gerar os sinais PWM ou PPM apropriados para controlar o dispositivo RC.

Construa um Transmissor RC Arduino Multifuncional: Guia DIY Passo a Passo
/* Projeto Transmissor RC Baseado em Arduino DIY == Código do Receptor - Controle ESC e Servo ==
por Dejan Nedelkovski, www.HowToMechatronics.com
Biblioteca: TMRh20/RF24, https://github.com/tmrh20/RF24/ */
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Servo.h>
RF24 radio(10, 9); // nRF24L01 (CE, CSN)
const byte address[6] = "00001";
unsigned long lastReceiveTime = 0;
unsigned long currentTime = 0;
Servo esc; // cria objeto servo para controlar o ESC
Servo servo1;
Servo servo2;
int escValue, servo1Value, servo2Value;
// Tamanho máximo desta struct é 32 bytes - limite do buffer NRF24L01
struct Data_Package {
  byte j1PotX;
  byte j1PotY;
  byte j1Button;
  byte j2PotX;
  byte j2PotY;
  byte j2Button;
  byte pot1;
  byte pot2;
  byte tSwitch1;
  byte tSwitch2;
  byte button1;
  byte button2;
  byte button3;
  byte button4;
};
Data_Package data; // Cria uma variável com a estrutura acima
void setup() {
  Serial.begin(9600);
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setAutoAck(false);
  radio.setDataRate(RF24_250KBPS);
  radio.setPALevel(RF24_PA_LOW);
  radio.startListening(); // Define o módulo como receptor
  resetData();
  esc.attach(9);
  servo1.attach(3);
  servo2.attach(4);
}
void loop() {
  // Verifica se continuamos recebendo dados, ou se temos conexão entre os dois módulos
  currentTime = millis();
  if (currentTime - lastReceiveTime > 1000) {
    resetData(); // Se a conexão for perdida, reseta os dados. Evita comportamento indesejado
  }
  // Verifica se há dados para receber
  if (radio.available()) {
    radio.read(&data, sizeof(Data_Package));
    lastReceiveTime = millis();
  }
  // Controlando servos
  servo1Value = map(data.j2PotX, 0, 255, 0, 180);
  servo2Value = map(data.j2PotY, 0, 255, 0, 180);
  servo1.write(servo1Value);
  servo2.write(servo2Value);
  // Controlando motor brushless com ESC
  escValue = map(data.pot1, 0, 255, 1000, 2000); // Mapeia valor recebido de 0-255 para 1000-2000, valores usados para controlar ESCs
  esc.writeMicroseconds(escValue); // Envia sinal de controle PWM para o ESC
}
void resetData() {
  data.j1PotX = 127;
  data.j1PotY = 127;
  data.j2PotX = 127;
  data.j2PotY = 127;
  data.j1Button = 1;
  data.j2Button = 1;
  data.pot1 = 1;
  data.pot2 = 1;
  data.tSwitch1 = 1;
  data.tSwitch2 = 1;
  data.button1 = 1;
  data.button2 = 1;
  data.button3 = 1;
  data.button4 = 1;
}

É isso. Espero que tenha gostado deste vídeo e aprendido algo novo. Sinta-se à vontade para fazer qualquer pergunta na seção de comentários abaixo e confira minha Coleção de Projetos Arduino.

Processo de manufatura

  1. O Kazoo: Do Mirliton Antigo ao Brinquedo Plástico Moderno – História, Fabricação e Futuro
  2. Construa Seu Próprio LUMAZOID: Visualizador de Música DIY com Arduino
  3. Construa Sua Própria Máquina de Escrever Deveres de Casa (Plotter de Caneta) em Casa
  4. Construa um Voltímetro Inteligente com Arduino e Smartphone – Projeto DIY Fácil
  5. Estação Meteorológica Compacta: Arduino Nano e ESP8266 com BMP280 e Display OLED/Nokia LCD
  6. Construa um Skate VR DIY com Arduino, Google Cardboard e Bluetooth
  7. Dispositivo de Tratamento Radiônico EMR DIY com Arduino Nano
  8. Simulador de Corrida 2D DIY com Arduino Nano e Servos SG90
  9. Construa uma Fechadura de Porta RFID Portátil com Arduino – Guia Passo a Passo
  10. CNC VMC 3 Eixos DIY: Construa uma Fresadora de Precisão