Para aqueles que querem se aventurar pelo mundo da robótica, um bom ponto de partida é montar e experimentar com um braço robótico. A experiência obtida no processo irá ajudar tanto no projeto quanto na programação envolvida e nos detalhes do processo.
Existem vários kits de braços robóticos no mercado. A Eletrogate oferece 3 kits: O AS5, o BT3-Mini e o Braço robótico em MDF. Neste artigo, abordaremos o braço robótico em MDF. Para um maior entendimento de conceitos de braços robóticos, recomendo o artigo Braço Robótico: O que são os Graus de Liberdade?.
Este kit contém várias placas em MDF (3 mm) já cortadas com todas as peças da estrutura, parafusos e porcas necessárias. Os 4 servos necessários devem ser comprados separadamente.
Para montar o kit, recomendo seguir as instruções contidas no manual disponibilizado pela Eletrogate. O manual segue o “estilo Lego”, mostrando as peças a selecionar e indicando com fotos as montagens parciais destas peças.
Para complementar as instruções do manual, gostaria de sugerir as seguintes dicas:
Dicas para após a montagem:
Complementando a dica de inicializar os servos em 90 graus antes da montagem, sugiro fazer as conexões dos horns considerando a configuração da foto abaixo, com o braço e antebraço em 90 graus entre si e com a base e com o braço orientado para a frente da base. Desta forma, o servo da base terá liberdade de 90 para cada lado e os servos horizontal e vertical poderão estender até os limites (menos de 90). Quanto ao servo da garra, sugiro, inicialmente, não aparafusar o horn. Como a engrenagem ligada a ele é parcial e o braço limita a excursão, além de bastante folga na engrenagem, algum ajuste pode ser necessário reposicionando o horn com a engrenagem. Uma vez que a faixa adequada para abertura e fechamento esteja definida, basta aparafusar o horn.
Para quem quiser imprimir o calço em 3D, este foi projetado na ferramenta OpenSCAD. O código está abaixo:
Wall = 1; CubeLIn = 58; CubeLOut = CubeLIn+ 2*Wall; CubeH = 3; radius = 30; CircleH = 1; MotorD =17.3; MotorWidth = 12.5; MotorLength = 23; MotorDeltaX = 12; MotorDeltaY = 11.27; tol = 2; //linear_extrude(CircleH); { difference() { union() { translate([MotorD,CubeLOut/2,CubeH]) linear_extrude(CircleH) circle(radius); difference() { cube([CubeLOut, CubeLOut, CubeH+CircleH]); translate([Wall,Wall,-1]) cube([CubeLIn, CubeLIn, CubeH+1]); } } translate([MotorDeltaX-tol/2,CubeLOut/2 - (MotorWidth+tol)/2 ,0]) cube ([MotorLength+tol,MotorWidth+tol, CubeH +CircleH + tol ]); }
Para entendermos os movimentos do braço, precisamos entender a sua geometria. Partindo da posição inicial, se acionarmos o servo de base, ele simplesmente gira o corpo em torno do eixo do motor. O funcionamento da garra também é simples, fechando as pinças conectadas ao servo por engrenagens.
Fazendo uma analogia com o braço humano, na figura abaixo podemos dizer que nosso braço robótico possui um braço (vermelho) e um antebraço (verde). Os servos a esquerda e direita do braço, chamados de vertical e horizontal, respectivamente, controlam os ângulos marcados em azul-claro. Ou seja, o servo horizontal controla o ângulo do braço com a base. O servo vertical controla o ângulo do antebraço com relação à horizontal (não com o braço). Além disso, a geometria do braço mantém a garra sempre na horizontal.
Para entendermos como isso é possível, podemos analisar as figuras abaixo. Todas as hastes de mesma cor sempre estarão paralelas entre si durante o movimento.
O servo horizontal (figura da esquerda) está conectado diretamente ao braço. Além disso, como este está conectado à peça triangular e a garra garante que a garra sempre estará na horizontal. Ou seja, podemos dizer que este motor controla o ângulo do corpo com o braço.
O servo vertical (figura da direita) aciona um pequeno braço que sempre estará paralelo ao antebraço (em verde). Sendo assim podemos dizer que este motor controla o ângulo do antebraço com relação ao corpo.
Com base nestas relações, usando um pouco de trigonometria, seria possível inclusive calcular as posições estimadas em algum sistema de coordenadas. Questões mecânicas introduziram um erro nestes cálculos, mas pode ser um exercício interessante para experimentos.
O responsável pelo movimento do nosso braço robótico é o servo. No nosso caso, usaremos o Micro Servo 9g SG90 TowerPro. É um servo pequeno e barato, ideal para aprendizado e situações de pequena carga. Suas engrenagens são de nylon, ao contrário dos seus irmãos maiores, que têm engrenagens de metal.
Cada servomotor contém uma conexão de 3 fios: Vcc, Gnd e sinal. O controle é feito por um sinal que é um pulso PWM (Pulse Width Modulation ou modulação por largura de pulso). Este servo em questão pode se mover entre 0 e 180 graus.
Para controlar os servomotores, existem algumas opções. A questão aqui é que o consumo destes motores é grande. Logo, a Uno não consegue alimentá-los. Por isso, precisamos de uma fonte externa. Para entender como usar servos com Arduino, veja este artigo: Servo Motor: Conheça Aplicações e Aprenda a Usar.
Além disso, o controle de motores pode gerar ruídos, o que pode ser reduzido por capacitores ou do isolamento dos circuitos de controle da Arduino. Recomendo a leitura do artigo Kit Braço Robótico MDF com Arduino, que aborda bem esta questão, controlando o braço com potenciômetros. Outro artigo interessante é o Braço Robótico com Joystick. É preciso um cuidado maior se o circuito for todo montado numa protoboard. Nos artigos em questão, foi utilizada uma Arduino UNO R3 com um sensor shield. Esse shield oferece algumas vantagens, como já usar uma entrada de fonte externa e já possuir jumpers que permitem conectar o servo direto na shield com a pinagem correta. Cada conexão de servo irá usar um pino digital da Arduino.
No nosso caso, usaremos uma solução diferente: o Módulo PWM PCA9685 I2C – 16 Canais para Servo.
O uso deste módulo, se comparado com a conexão direta à Arduino (shield ou protoboard), tem algumas vantagens e desvantagens. Para começar, ele permite controlar até 16 servos. A comunicação com a Arduino é feita pelo protocolo I₂C, que usa apenas 2 pinos. O endereço I₂C pode ser alterado na placa, permitindo utilizar até 62 módulos no mesmo circuito, aumentando assim a quantidade de servos a serem controlados (até 992 saídas). O módulo já contém um capacitor de 1000 uF para redução de ruídos. Além disso, por ser um controlador separado, ele reduz a carga de processamento da Arduino, o que pode ser útil em programas mais complexos.
As desvantagens seriam o custo adicional e não permitir uma montagem compacta como o sensor shield. Em especial no braço robótico em MDF, já existe furação para fixar a Arduino na parte traseira, bastando fixar o shield acima dela. No nosso caso, colocamos o módulo numa protoboard a parte.
Na programação, para utilizar o módulo é necessário usar a biblioteca Adafruit_PWMServoDriver.h, ao invés da Servo.h, usada quando conectamos direto à Arduino (com ou sem shield). Os comandos usados são:
No blog, já existem artigos controlando o braço robótico com potenciômetros e com joystick. Neste artigo, optamos por apresentar um controle usando o celular com bluetooth. Para isso, usamos o Módulo Bluetooth HC-06. Este módulo contém 4 pinos: Vcc, Gnd, Rx e Tx. Um detalhe importante é que, ao conectar ao Rx, deve ser respeitado o limite de 3.3V. Por isso, é utilizado um divisor resistivo para reduzir o sinal da Arduino de 5V para 3.3V. O Tx também é 3.3V, mas é um nível suficiente para a Arduino reconhecer como “1”.
O módulo HC-06 já foi bem explicado no artigo Módulos Bluetooth HC05 e HC06 para Comunicação com Dispositivos Móveis com Arduino.
Os comandos usados são:
Para acessar este módulo no celular, usaremos o App Arduino Bluetooth Control. Este aplicativo oferece várias opções de comunicação. Para simplificar, usaremos 2 delas: Botões e Setas. Temos 4 motores a comandar. Sendo assim, na nossa programação, estipulamos 8 comandos:
Abaixo, vemos a tela principal, com ícones de conexão e configuração na parte superior da tela à direita. Podemos ver as diversas ferramentas disponíveis. Usaremos as setas (Arrow Keys) e os botões (Buttons & Slider)
A opção de botões do aplicativo nos oferece apenas 6 botões. Por isso, o controle da garra foi feito na opção de Setas. Abaixo, podemos ver as telas de setas e botões, acessíveis pela tela principal.
Para configurar o aplicativo, primeiro deve-se clicar na imagem de robô à direita, no topo. No menu, a opção “Keys configuration” (Arrows Keys) permite associar a cada uma das setas um valor. No mesmo menu, é possível configurar os botões em “Command buttons configuration”.
Uma vez configurado e com o circuito pronto e energizado, no topo da tela principal, existe um ícone para conectar. Ao clicá-lo, o HC-06 deve aparecer na lista. Ao clicar no HC-06, a conexão será feita e você já poderá controlar o braço robótico.
No programa, cada comando altera o ângulo do respectivo servo em 5 graus.
O circuito e suas conexões podem ser vistos na figura abaixo. As conexões dos servos ao módulo PWM foram conectadas nas entradas 0 a 3 na seguinte ordem: Base, Vertical, Horizontal, Garra.
O diagrama acima não mostra as conexões dos servos. Estes conectores devem ser conectados diretamente ao módulo PWM, respeitando a posição dos fios: marrom é GND, vermelho V+ e laranja PWM. Os servos são ligados nas posições 0 a 3 na seguinte ordem: base, vertical, horizontal, garra. O conector da garra precisa ser conectado com o cabo extensor (sinal em branco, não laranja). As conexões podem ser vistas na foto da montagem mais abaixo.
Cabe aqui uma observação sobre a protoboard de 830 pinos e a alimentação do circuito. Esta protoboard tem 2 pares de alimentação no topo e abaixo. Porém, cada fileira também é dividida no meio. Neste circuito usamos uma alimentação externa nas fileiras de cima, unidas por dois fios. Estas alimentam apenas os servos através do módulo PWM.
Na parte inferior direita, a alimentação vem da Arduino, que, por sua vez, vem da porta USB do PC, quando conectado para programação e testes. Porém, o terra é comum com a fonte conectada com a protoboard, através de conexão de fio na protoboard.
Para a alimentação da fonte da protoboard, utilizei uma fonte de celular de 5V / 400 mA conectada à entrada USB. Funcionou, porém seria recomendado uma fonte capaz de 1 A. Cada servo consome de 10 mA a 250 mA em carga nominal máxima. Porém, se travarem, podem consumir até 0.7 A. Se a montagem do braço robótico estiver ok, a carga é bem baixa e não haverá travamento. A exceção seria a garra, caso estava segurando um objeto com muita força.
Esta fonte para protoboard permite também entrada de uma fonte de 7-10 V via plug P4. Porém, é preciso tomar cuidado com a entrada, pois, se ultrapassado o limite de 10 V, a fonte pode falhar e repassar uma tensão alta para a saída, queimando os servos (experiência própria com bateria de 12 V). Por isso, recomendo usar uma fonte de 5 volts, por segurança.
Uma alternativa, que acredito ser a mais segura, seria alimentar diretamente o conector do módulo PWM com Fonte 5V + Conector Adaptador Plug P4 Femea com Borne KRE.
Abaixo, segue foto da protoboard usando a fonte para protoboard MB102.
Antes de começar a usar o braço robótico, para evitar danos, sugiro ligar cada motor individualmente para verificar seus limites e fazer os ajustes necessários. No programa, existem arrays com os limites inferior e superior (servo_limite_inf e servo_limite_sup). Existe também uma array com os valores iniciais quando a Arduino é ligada (servo_inicial). Os limites podem ser alterados para 0 e 180 durante a calibragem e identificação dos valores corretos.
Todos estes valores foram obtidos por experimentação, testando um motor de cada vez e identificando os limites de movimento que a garra permite. Na montagem, sugeri que os servos fossem iniciados em 90 graus. Mas, dependendo da posição do braço na montagem, pode ser necessário reconectar os horns. Lembre que os servos têm o limite de 0 a 180.
Reposicionar os servos da garra e da base é simples, pois os horns são de fácil acesso. Basta dar o comando do servo para uma posição central (90?), desparafusar o horn sem girar o motor, reposicionar o horn numa posição adequada (~metade do movimento) e reaparafusar.
Para os servos de movimento vertical e horizontal o procedimento é semelhante, mas se faz necessário desparafusar a lateral do corpo do braço antes, para ter acesso ao parafuso do horn. Para o servo vertical são dois parafusos na base da lateral. Para o servo horizontal, é preciso desaparafusar os dois da base da lateral e um do braço.
Abaixo é possível ver os servos vertical e horizontal, respectivamente, já com a lateral desconectada e movida para uma posição onde os parafusos dos horns estão acessíveis. Perceba o ângulo de 90 graus dos braços conectados aos horns com relação a lateral da base. Ao final, basta reencaixar e aparafusar novamente.
Este procedimento só é necessário caso o posicionamento correto não tenha sido feito durante a montagem e se o movimento dos servos estiver limitado. Caso contrário, basta ajustar a posição inicial e os limites no programa.
Um vez que todos os servos estejam conectados adequadamente, mova cada um até os limites que o braço permite e atualize os valores das arrays de limites e posição inicial citadas acima.
Para melhor entendimento do código, segue uma lista das funções e suas atribuições:
/* Programa de controle de braço robótico em MDF via Bluetooth Blog Eletrogate - https://blog.eletrogate.com/ Arduino Uno - IDE 2.1.1 Mauro Vianna 11/julho/2023 */ #include <Wire.h> #include <Adafruit_PWMServoDriver.h> #include <SoftwareSerial.h> //Biblioteca para conectar com o bluetooth (já vem instalado), não precisa baixar SoftwareSerial serialdobluetooth(8,9); // Portas para o serial do bluetooth (RX, TX) Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); // objeto de controle PWM dos servos #define SERVOMIN 125 // this is the 'minimum' pulse length count (out of 4096) #define SERVOMAX 575 // this is the 'maximum' pulse length count (out of 4096) uint8_t numberOfServos = 4; // Identificação dos servos #define SV_BASE 0 #define SV_VERTICAL 1 #define SV_HORIZONTAL 2 #define SV_GARRA 3 #define NUM_SERVOS 4 // Arrays dos servos float servo_target[NUM_SERVOS]; // posição alvo de movimento int servo_limite_inf[NUM_SERVOS] = {0, 45, 90,30}; // Limite inferior do ângulo do servo int servo_limite_sup[NUM_SERVOS] = {180, 140, 175, 160}; // Limite superior do ângulo do servo int servo_inicial[NUM_SERVOS] = {90, 120, 90, 30}; // Posição inicial do ângulo do servo float delta = 5; // Movimento do ângulo por cada comando // Definição dos comandos #define CMD_NULO 0 #define CMD_ESQ 'A' #define CMD_DIR 'a' #define CMD_AVANCA 'B' #define CMD_RECUA 'b' #define CMD_SOBE 'C' #define CMD_DESCE 'c' #define CMD_ABRE 'D' #define CMD_FECHA 'd' int comando; // comando a ser executado //int valordobluetooth; // Variável que vai ler o valor enviado pelo bluetooth // Inicialização void setup() { serialdobluetooth.begin(9600); // Início da serial do bluetooth Serial.begin(9600); // Início da serial com o PC pwm.begin(); // Inicialização do PWM pwm.setPWMFreq(60); delay(10); // Move servos para posição inicial for (int i = 0; i<= numberOfServos; i++ ) { servo_target[i] = servo_inicial[i]; Serial.print("Alvo: ");Serial.print(i); Serial.print(" : ");Serial.println(servo_inicial[i]); } moveServos(); } // Loop principal : Lê comando via Bluetooth e processa void loop() { // put your main code here, to run repeatedly: // moveToAngle(0,90); comando = leComando(); if (comando != CMD_NULO) { processaComando(comando); } //delay(100); moveServos(); } // Faz a leitura de comando do bluetooth. Na ausência de comando retorna CMD_NULO int leComando() { if (serialdobluetooth.available()) //Se o bluetooth estiver funcionando, vai ser lido o "valor", para reproduzir o comando { return serialdobluetooth.read(); } else { return CMD_NULO; } } // Processa cada comando void processaComando(int cmd) { int garra; switch (cmd) { case CMD_ESQ: // statements setservoTarget(SV_BASE,servo_target[SV_BASE] + delta); Serial.print("<< base "); Serial.print(" | "); Serial.println(servo_target[SV_BASE]); break; case CMD_DIR: setservoTarget(SV_BASE,servo_target[SV_BASE] - delta); Serial.print("base >>"); Serial.print(" | "); Serial.println(servo_target[SV_BASE]); break; case CMD_SOBE: setservoTarget(SV_VERTICAL,servo_target[SV_VERTICAL] - delta); Serial.print("sobe"); Serial.print(" | "); Serial.println(servo_target[SV_VERTICAL]); break; case CMD_DESCE: setservoTarget(SV_VERTICAL, servo_target[SV_VERTICAL] + delta); Serial.print("desce"); Serial.print(" | "); Serial.println(servo_target[SV_VERTICAL]); break; case CMD_AVANCA: setservoTarget(SV_HORIZONTAL,servo_target[SV_HORIZONTAL] - delta); Serial.print("avança >>"); Serial.print(" | "); Serial.println(servo_target[SV_HORIZONTAL]); break; case CMD_RECUA: setservoTarget(SV_HORIZONTAL, servo_target[SV_HORIZONTAL] + delta); Serial.print("<< recua"); Serial.print(" | "); Serial.println(servo_target[SV_HORIZONTAL]); break; case CMD_ABRE: setservoTarget(SV_GARRA, servo_target[SV_GARRA] - delta); Serial.print("<< abre >>"); Serial.print(" | "); Serial.println(servo_target[SV_GARRA]); break; case CMD_FECHA: // statements setservoTarget(SV_GARRA, servo_target[SV_GARRA] + delta); Serial.print(">> fecha <<"); Serial.print(" | "); Serial.println(servo_target[SV_GARRA]); break; default: break; } } // Move todos os servos void moveServos() { for (int i = 0; i<= numberOfServos; i++ ) { moveToAngle(i,servo_target[i]); } } // Move servo para angulo designado enviando o pulso correspondente void moveToAngle(int servo, float angle) { pwm.setPWM(servo, 0, angleToPulse(angle) ); } // Converte o valor do ângulo para o pulso correspondente int angleToPulse(int ang){ int pulse = map(ang,0, 180, SERVOMIN,SERVOMAX);// map angle of 0 to 180 to Servo min and Servo max return pulse; } // Muda o ângulo alvo do servo, respeitando os limites configurados void setservoTarget(int Servo, float target) { int valor; valor = target; valor = min(valor,servo_limite_sup[Servo]); valor = max(valor,servo_limite_inf[Servo]); servo_target[Servo] = valor; }
Abaixo, um vídeo curto mostrando a operação do braço robótico:
Existem várias opções de como usar este tipo de controle para executar comandos. Usamos o controle direto dos servos. Porém, cada comando poderia acionar movimentos para determinadas posições, ou até sequências de movimentos. Por exemplo, um comando poderia voltar o braço para posição inicial. Outro poderia ser uma sequência de movimentos para pegar um objeto X. E outro uma sequência para soltar em uma posição Y. Ou, quem sabe, até uma “dancinha”?
O controlador PWM usado permitiria até controlar mais braços robóticos deste tipo (até 4) com a mesma Arduino.
Os comandos executam um movimento de 5 graus. É possível mudar isso mudando a variável delta para um movimento mais suave, porém mais lento. Outra opção para suavizar o movimento seria mover por passos menores. Por exemplo, ao dar um comando de alteração de 5 graus, o programa poderia fazer uma repetição de movimentos menores (5 passos de 1 grau?) para suavizar.
O aplicativo Android Bluetooth Controller possui outros recursos interessantes a explorar. Na tela de botões, ao girar o celular existe um slider. Em teoria este poderia ser usado para controlar a garra, mas demandaria programação adequada. A ferramenta Terminal permite também enviar comandos e receber mensagens da Arduino. Pode ser interessante para implementar comandos mais complexos.
Vimos, neste artigo, o uso do braço robótico em MDF de uma forma alternativa a outros artigos, usando um controlador de servos e controle por bluetooth. Este braço permite uma ampla gama de experimentações, sendo um excelente ponto de partida para aqueles que estão iniciando suas aventuras com robótica. Abordaremos mais aspectos deste kit em artigos futuros.
|
A Eletrogate é uma loja virtual de componentes eletrônicos do Brasil e possui diversos produtos relacionados à Arduino, Automação, Robótica e Eletrônica em geral.
Tenha a Metodologia Eletrogate dentro da sua Escola! Conheça nosso Programa de Robótica nas Escolas!