Desenvolvimento de Robô Bípede com Arduino Uno e Cinemática Inversa

A construção de um robô bípede exige não apenas precisão mecânica, mas também um controle lógico refinado para coordenar os movimentos de múltiplas articulações de forma síncrona. Utilizando uma placa Arduino Uno, é possível controlar seis servomotores que compõem os eixos das pernas (quadril, joelho e tornozelo), permitindo a execução de ciclos de caminhada baseados em cálculos trigonométricos.

Configuração de Hardware e Constantes

O sistema baseia-se na definição de offsets e dimansões físicas das hastes do robô. Estes valores são cruciais para garantir que a posição "zero" do software corresponda à postura vertical correta do hardware.

// Definição de offsets para calibração dos servos
#define OFF_QUADRIL_E 105   
#define OFF_JOELHO_E  155   
#define OFF_TORNOZELO_E 85   

#define OFF_QUADRIL_D 82    
#define OFF_JOELHO_D 25   
#define OFF_TORNOZELO_D 85    

// Dimensões dos membros (em cm)
#define COMP_COXA 5.0
#define COMP_PERNA 5.7

// Parâmetros de movimentação
#define ALTURA_PASSO 1.0
#define ELEVACAO_BASE 10.0

Implementação da Cinemática e Movimentação

O núcleo do controle reside na conversão de coordenaads Cartesianas (X, Z) em ângulos para os servos, utilizando a lei dos cossenos para resolver a cinemática inversa das pernas.

#include <Servo.h>
#include <math.h>

Servo s_quadrilE, s_quadrilD, s_joelhoE, s_joelhoD, s_tornozeloE, s_tornozeloD;

void atualizarAtuadores(int angQ, int angJ, int angT, char lado) {
  if (lado == 'E') {
    s_quadrilE.write(OFF_QUADRIL_E - angQ);
    s_joelhoE.write(OFF_JOELHO_E - angJ);
    s_tornozeloE.write(2 * OFF_TORNOZELO_E - angT);
  } else {
    s_quadrilD.write(OFF_QUADRIL_D + angQ);
    s_joelhoD.write(OFF_JOELHO_D + angJ);
    s_tornozeloD.write(angT);
  }
}

void calcularTrajetoria(float eixoX, float eixoZ, char lado) {
  float radBase = atan(eixoX / eixoZ);
  float degBase = radBase * (180.0 / PI);

  float hipotenusa = eixoZ / cos(radBase);

  // Aplicação da Lei dos Cossenos para determinar os ângulos internos
  float radQuadril = acos((sq(COMP_COXA) + sq(hipotenusa) - sq(COMP_PERNA)) / (2 * COMP_COXA * hipotenusa));
  float degQuadril = radQuadril * (180.0 / PI);
  
  float radJoelho = PI - acos((sq(COMP_COXA) + sq(COMP_PERNA) - sq(hipotenusa)) / (2 * COMP_COXA * COMP_PERNA));
  float degJoelho = radJoelho * (180.0 / PI);

  float radTornozelo = (PI / 2) + radBase - acos((sq(COMP_PERNA) + sq(hipotenusa) - sq(COMP_COXA)) / (2 * COMP_PERNA * hipotenusa));
  float degTornozelo = radTornozelo * (180.0 / PI);

  atualizarAtuadores(degQuadril + degBase, degJoelho, degTornozelo, lado);
}

void cicloCaminhada(float amplitude, int velocidade) {
  // Fase 1: Movimento da perna direita
  for (float i = amplitude; i >= -amplitude; i -= 0.5) {
    calcularTrajetoria(i, ELEVACAO_BASE, 'D');
    calcularTrajetoria(-i, ELEVACAO_BASE - ALTURA_PASSO, 'E');
    delay(velocidade);
  }

  // Fase 2: Movimento da perna esquerda
  for (float i = amplitude; i >= -amplitude; i -= 0.5) {
    calcularTrajetoria(-i, ELEVACAO_BASE - ALTURA_PASSO, 'D');
    calcularTrajetoria(i, ELEVACAO_BASE, 'E');
    delay(velocidade);
  }
}

void setup() {
  s_quadrilE.attach(9);
  s_quadrilD.attach(8);
  s_joelhoE.attach(7);
  s_joelhoD.attach(6);
  s_tornozeloE.attach(5);
  s_tornozeloD.attach(4);

  // Posição inicial estável
  atualizarAtuadores(0, 0, OFF_TORNOZELO_E, 'E');
  atualizarAtuadores(0, 0, OFF_TORNOZELO_D, 'D');
  
  delay(3000);
}

void loop() {
  cicloCaminhada(2.0, 45);
}

Lógica de Funcionamento

O algoritmo de caminhada utiliza um laço de repetição que interpola a posição horizontal (eixxo X). Enquanto uma perna avança em uma trajetória linear, a outra compensa a altura para manter o equilíbrio e o descolamento do chão. A função calcularTrajetoria abstrai a complexidade matemática, transformando as coordenadas de destino em pulsos PWM para os servos.

A precisão do movimento depende diretamente da calibração dos offsets iniciais. Caso o robô apresente instabilidade, recomenda-se ajustar as constantes de altura da passada ou reduzir a velocidade de transição entre os estados dos motores.

Tags: Arduino Robótica CinemáticaInversa servomotores C++

Publicado em 7-13 07:14