LusoRobótica - Robótica em Português

Robótica => Tutoriais => Tópico iniciado por: guibot em 21 de Agosto de 2009, 19:14

Título: Suavizar movimentos dos servos
Enviado por: guibot em 21 de Agosto de 2009, 19:14
Já ando de volta disto à bastante tempo, e finalmente decidi-me a publicar os resultados obtidos  :)

No video que segue vão ver duas experiências distintas. Primeiro com os servos ligados directamente ao arduino e de segundo com o controlador de servos - pololu micro serial servo controller. (http://<a href="http://www.pololu.com/catalog/product/207">)

O controlador da pololu dá-nos uma boa possibilidade de definir velocidade, e em conjunto com o filtro de suavização conseguem-se movimentos verdadeiramente suaves, podem ver mesmo no final do video.

O robot treme bastante mas isso deve-se à sua estrutura de suporte frágil, é apenas um ferro que o suporta e facilmente ele desata a tremer. Tenho que arranjar outra solução para ficar bem fixo.

Código fonte depois do video  ;)

http://www.youtube.com/watch?v=g6uo2K8M6BM&feature=player_embedded

Código para usar os servos directamente ligados ao arduino:
Código: [Seleccione]
// suavizar movimentos de um servo
// para correres este código o sinal do servo deverá
// estar directamente ligado ao pin 2 do arduino

// Intervalo de tempo, correr uma porção de código de tempo a tempo
// Download da biblioteca Metro e Instruções:
// http://www.arduino.cc/playground/Code/Metro
#include <Metro.h>
int duration = 3500; // duração do intervalo em milisegundos
Metro intervaller = Metro (duration);

// Biblioteca MegaServo
// Download da biblioteca e Instruções:
// http://www.arduino.cc/playground/Code/MegaServo
#include <MegaServo.h>
MegaServo servos;

// posições máxima e mínima do servo, equivalente a 0 e 180º
#define MIN_POS 800
#define MAX_POS 2200

// servo pin
#define s0_pin 2

// variáveis para armazenar novas posições de destino do servo
int d0; // destino0
int d0_sh; // destino0 com suavização, "_sh" = smooth

// variável que contem o valor do filtro que vai ser aplicado
// este valor vai ser multiplicado pelo d0 e pelo d0_sh
float filtro = 0.05; // 0.01 to 1.0

// função de inicialização, correr uma vez quando o programa é inciado
void setup() {
  // inicializa comunicação serial
  Serial.begin(9600);
 
  // define pin onde vai estar o servo
  servos.attach(s0_pin);
}

// programa loop(), função que corre eternamente
void loop() {
 
  // analiza o intervalo de tempo, sempre que chega ao limite da duração volta a 1
  // e correr o código que estiver entre {}
  if (intervaller.check() == 1) {
   
    // calcula nova posição aleatória entre os valores min e max
    d0 = random(MIN_POS, MAX_POS);
   
    // reinicia intervalo de tempo com valor aleatório
    intervaller.interval(random(500,2000));
   }
 
  // suavizar o valor de destino
  d0_sh = d0_sh * (1.0-filtro) + d0 * filtro;
 
  // atribui o valor de destino à posição do servo
  servos.write(d0_sh);
 
  // delay para dar tempo ao servo de se mover
  delay(25);
}




Código para o controlador da pololu:
Código: [Seleccione]
// suavizar movimentos de um servo
// para correres este código precisas de Pololu Micro Serial Servo Controller
// http://www.pololu.com/catalog/product/207

// Intervalo de tempo, correr uma porção de código de tempo a tempo
// Download da biblioteca Metro e Instruções:
// http://www.arduino.cc/playground/Code/Metro
#include <Metro.h>
int duration = 3500; // duration of the interval in miliseconds
Metro intervaller = Metro (duration);

// posições máxima e mínima do servo, equivalente a 0 e 180º
#define MIN_POS 500
#define MAX_POS 5500

// variáveis para armazenar novas posições de destino do servo
int d0; // destino0
int d0_sh; // destino0 com suavização, "_sh" = smooth

// variável que contem o valor do filtro que vai ser aplicado
// este valor vai ser multiplicado pelo d0 e pelo d0_sh
float filtro = 0.05; // 0.01 to 1.0

// define velocidade do servo, pode ser um valor entre 0 e 127
int servoSpeed = 120;

// função de inicialização, correr uma vez quando o programa é inciado
void setup() {
  // inicializa comunicação serial
  Serial.begin(9600);
 
  // define pin onde vai estar o servo
  servoSetSpeed(0, servoSpeed);
}

// programa loop(), função que corre eternamente
void loop() {
 
  // analiza o intervalo de tempo, sempre que chega ao limite da duração volta a 1
  // e correr o código que estiver entre {}
  if (intervaller.check() == 1) {
   
     // calcula nova posição aleatória entre os valores min e max
    d0 = random(MIN_POS, MAX_POS);
   
    // reinicia intervalo de tempo com valor aleatório
    intervaller.interval(random(500,3000));
  }
 
  // suavizar o valor de destino
  d0_sh = d0_sh * (1.0-filtro) + d0 * filtro;
 
  // atribui o valor de destino à posição do servo
  put(0,d0_sh);
 
  // delay para dar tempo ao servo de se mover
  delay(25);
}


// as funções seguintes foram retiradas deste tópico:
// http://forum.pololu.com/viewtopic.php?f=16&t=745&start=60&st=0&sk=t&sd=a

void put(int servo, int angle)
{
  //servo is the servo number (typically 0-7)
  //angle is the absolute position from 500 to 5500

  unsigned char buff[6];

  unsigned int temp;
  unsigned char pos_hi,pos_low;

  //Convert the angle data into two 7-bit bytes
  temp=angle&0x1f80;
  pos_hi=temp>>7;
  pos_low=angle & 0x7f;

  //Construct a Pololu Protocol command sentence
  buff[0]=0x80; //start byte
  buff[1]=0x01; //device id
  buff[2]=0x04; //command number
  buff[3]=servo; //servo number
  buff[4]=pos_hi; //data1
  buff[5]=pos_low; //data2

  //Send the command to the servo controller
  for(int i=0;i<6;i++){
    Serial.print(buff[i],BYTE);
  }

}

void servoSetSpeed(int servo, int speed){
  //servo is the servo number (typically 0-7)
  //speed is servo speed (1=fastest, 127=slowest)
  //set speed to zero to turn off speed limiting

  unsigned char buff[5];
  unsigned char speedcmd;

  speedcmd=speed&0x7f;//take only lower 7 bits of speed

  buff[0]=0x80;//start byte
  buff[1]=0x01;//device id
  buff[2]=0x01;//command number
  buff[3]=servo;//servo number
  buff[4]=speed;//data1

  for(int i=0;i<5;i++){
    Serial.print(buff[i],BYTE);
  }
}





Título: Re:Suavizar movimentos dos servos
Enviado por: jspgresende em 21 de Agosto de 2009, 22:55
Para o meu braço robótico tive de fazer a mesma coisa...
Interpolar o movimento de modo a criar X pontos para uma curva de aceleração em forma de "S" ...
Título: Re:Suavizar movimentos dos servos
Enviado por: guibot em 21 de Agosto de 2009, 23:27
Fantástico! e não nos queres mostrar o teu braço robótico?  :p
Título: Re:Suavizar movimentos dos servos
Enviado por: jspgresende em 22 de Agosto de 2009, 00:27
tens aqui o "canal" da coisa
os servos é que não são os melhores... como são muito fracos por vezes ele oscila um bocado
http://www.youtube.com/user/era1x
Título: Re:Suavizar movimentos dos servos
Enviado por: guibot em 22 de Agosto de 2009, 00:50
pois, é o mesmo problema que eu tenho.
Título: Re:Suavizar movimentos dos servos
Enviado por: guibot em 22 de Agosto de 2009, 08:25
comentários em português adiccionados ao código ;)
Título: Re:Suavizar movimentos dos servos
Enviado por: TigPT em 22 de Agosto de 2009, 11:39
Sim senhor... agora já não dá só para karaté, também dá para bailado :D
Título: Re:Suavizar movimentos dos servos
Enviado por: andnobre em 22 de Agosto de 2009, 13:18
bruce lee em accao.
muito fixe
Título: Re:Suavizar movimentos dos servos
Enviado por: guibot em 22 de Agosto de 2009, 14:18
 :D

a investigação continua, pois isto ainda vai vais longe ;)
Título: Re:Suavizar movimentos dos servos
Enviado por: zordlyon em 10 de Março de 2010, 12:58
tens aqui o "canal" da coisa
os servos é que não são os melhores... como são muito fracos por vezes ele oscila um bocado
http://www.youtube.com/user/era1x (http://www.youtube.com/user/era1x)

Muito bom, o braço robotico esta fenomenal, e o trabalho do sr. Guilherme e sem duvida uma boa utilidade para coisas que necessitem de precisão.

Cumprimentos...