Rotacionar Servomotor 180º + Sensor Ultrassonico

1,106 views
Skip to first unread message

Paulo Ferreira

unread,
Nov 28, 2011, 3:26:31 PM11/28/11
to ardu...@googlegroups.com
Pessoal, eu sou novo aqui na comunidade, e a pouco tempo adquiri alguns componentes para fazer testes com arduino. Primeiro eu adquiri a plataforma boebot e estou adaptando para arduino. Eu planejo fazer um carrinho simples, com um sensor ultrassonico na parte superior, mas esse sensor não fica parado, ele fica se movendo de 0 a 180 graus (direita e esquerda), com ajuda de um servo motor e um suporte para sensor ultrassonico. Meu primeiro problema é, como faço para ele verificar a distancia de um obstáculo e ao mesmo tempo girar para direita e esquerda. Eu coloquei os 2 para funcionar, mas apenas funciona 1 de cada vez. Gostaria que vocês me ajudassem nessa programação.


#include <Servo.h> 

Servo myservo;  // create servo object to control a servo
const int pingPin = 7;
int pos = 0;

void setup() {
  // initialize serial communication:
  Serial.begin(9600);
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
}

void loop()
  { 
  for(pos = 0; pos < 180; pos += 1)  // goes from 0 degrees to 180 degrees 
  {                                  // in steps of 1 degree 
    myservo.write(pos);     // tell servo to go to position in variable 'pos' 
    pingsensor();
    delay(15);                       // waits 15ms for the servo to reach the position 
  } 
  for(pos = 180; pos>=1; pos-=1)     // goes from 180 degrees to 0 degrees 
  {                                
    myservo.write(pos);              // tell servo to go to position in variable 'pos' 
    pingsensor();
    delay(15);                       // waits 15ms for the servo to reach the position 
  } 
}

void pingsensor(){
 long duration, inches, cm;

  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);

  pinMode(pingPin, INPUT);
  duration = pulseIn(pingPin, HIGH);

  inches = microsecondsToInches(duration);
  cm = microsecondsToCentimeters(duration);
  
  Serial.print(inches);
  Serial.print("in, ");
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();
  
  delay(100);  
}

long microsecondsToInches(long microseconds)
{
  return microseconds / 74 / 2;
}

long microsecondsToCentimeters(long microseconds)
{
  return microseconds / 29 / 2;
}

A programação acima fica da seguinte forma, ao invés do sensor ultrassonico trabalhar normalmente em conjunto com o servo, a cada repetição do "for" ele capta a distância do obstáculo, ou seja, de 0 a 180 a cada grau ele verifica um pulso do sensor (ele fica muito lento), que na verdade eu gostaria que eles trabalhassem paralelamente. Gostaria de uma solução, porque eu estou nisso há dias.

Desde já, Obrigado!

Carlos Eduardo "Mascote" Garcia de Carvalho

unread,
Nov 28, 2011, 3:38:57 PM11/28/11
to ardu...@googlegroups.com
1) Retire ou diminua o delay(100); também aumente o incremento do laço para 5º ou 10º.

Caso a sua necessidade seja realmente de grau em grau podemos pensar em alguma outra forma.

O uso de delay é sempre muito complicado porque ele força o microcontrolador a ficar parado naquele ponto do programa.

[]'s


---
Carlos Eduardo "Mascote" Garcia de Carvalho
"Reconhece-o em todos os teus caminhos, e ele endireitará as tuas veredas." Provérbios 3.6
(21) 8125-1737
Skype: carloseduardo.gc


2011/11/28 Paulo Ferreira <paulofs...@gmail.com>

Paulo Ferreira

unread,
Nov 28, 2011, 3:41:17 PM11/28/11
to ardu...@googlegroups.com
Em resumo, gostaria de fazer o servo motor girar 180º para direita e para esquerda, com o sensor ultrassonico preso a ele, desviando os obstáculos pela frente, mas não consigo fazer isso simultâneamente.

Fernando Oliveira

unread,
Nov 28, 2011, 3:47:07 PM11/28/11
to ardu...@googlegroups.com
pq vc não faz algo parecido com:

<code>
// codigo não compilado nem testado...

int incrServo       = 1;
int posServo       = 0
int nextIncrServo = 0;

void loop() {
   rodaServo();
   pingSensor();
}

void rodaServo() {
   if(nextIncrServo <= millis()) {
      if(posServo <= 0 || posServo >= 180) incrServo *= -1;
      posServo += incrServo;
      myservo.write(posServo);
      nextIncrServo = millis() + 15;
   }
}

</code>
e o pingServo ficaria igual...

Just another Perl Hacker,
Fernando (SmokeMachine)
sip:f...@pbxes.org

Fernando Oliveira

unread,
Nov 28, 2011, 3:50:13 PM11/28/11
to ardu...@googlegroups.com
Provavelmente tem alguma coisa errada nesse codigo (eu escrevi direto no email... não tenho como testar no trabalho...)

millis() é mesmo a func q retorna a qtos milisegundos o arduino tá ligado?


Just another Perl Hacker,
Fernando (SmokeMachine)
sip:f...@pbxes.org


Fernando Oliveira

unread,
Nov 28, 2011, 3:55:08 PM11/28/11
to ardu...@googlegroups.com
esquecí 1 ";" no "int posServo = 0;"...

Just another Perl Hacker,
Fernando (SmokeMachine)
sip:f...@pbxes.org


Fernando Corrêa de Oliveira

unread,
Nov 28, 2011, 4:45:59 PM11/28/11
to ardu...@googlegroups.com
Paulo,

Resolveu o seu problema?

JAPH

Carlos Eduardo "Mascote" Garcia de Carvalho

unread,
Nov 28, 2011, 4:55:46 PM11/28/11
to ardu...@googlegroups.com
No if
   if(nextIncrServo <= millis()) {

Não seria
   if(nextIncrServo => millis()) {

?

---
Carlos Eduardo "Mascote" Garcia de Carvalho
"Reconhece-o em todos os teus caminhos, e ele endireitará as tuas veredas." Provérbios 3.6
(21) 8125-1737
Skype: carloseduardo.gc


2011/11/28 Fernando Corrêa de Oliveira <fernand...@gmail.com>

Fernando Corrêa de Oliveira

unread,
Nov 28, 2011, 5:22:54 PM11/28/11
to ardu...@googlegroups.com
Não, como eu ponho o valor da próxima rotação na variável (mills() + tempo) eu tenho q verificar se o tempo atual é => (maior ou igual) ao tempo atual.

JAPH

Fernando Corrêa de Oliveira

unread,
Nov 28, 2011, 5:55:00 PM11/28/11
to ardu...@googlegroups.com
quer dizer:

eu guardo na variavel a hora atual + o tempo q eu devo esperar.
ele só deve rotacionar quando o valor da variavel for menor ou igual (<=) ao tempo atual!
ou seja, qdo o tempo atual for igual ou já tiver passado do tempo em que deve rotacionar denovo...

Just Another Perl Hacker

Fernando Corrêa de Oliveira
fernand...@gmail.com

Paulo Ferreira

unread,
Nov 28, 2011, 6:41:54 PM11/28/11
to ardu...@googlegroups.com
Obrigado pela atenção de vocês, eu cheguei agora em casa vou testar e já passo algo para vocês.

Fernando Oliveira

unread,
Nov 29, 2011, 6:52:11 AM11/29/11
to ardu...@googlegroups.com
E então? funcionou?


Just another Perl Hacker,
Fernando (SmokeMachine)


Paulo Ferreira

unread,
Nov 29, 2011, 6:55:52 AM11/29/11
to ardu...@googlegroups.com
Fernando, eu fiz as alterações que você indicou, mas ainda não chegamos ao esperado. No momento que que passei pro arduino o servo girou completamente para direita e não voltou, e outra coisa eu percebi, que o sensor não captava completamente os pulsos, por exemplo, quando eu abri a conexão serial ele mostrava, 53, 55, 58, 0, 62, 61, 0. Mas de qualquer forma, obrigado pela ajuda.

Estou enviando duas imagens do meu protótipo, para vocês terem uma ideia.
DSC01515_.jpg
DSC01516_.jpg

Fernando Oliveira

unread,
Nov 29, 2011, 6:57:08 AM11/29/11
to ardu...@googlegroups.com
Me manda o codigo como ficou...


Just another Perl Hacker,
Fernando (SmokeMachine)
sip:f...@pbxes.org

Paulo Ferreira

unread,
Nov 29, 2011, 6:59:57 AM11/29/11
to ardu...@googlegroups.com
#include <Servo.h>

Servo myservo;  // create servo object to control a servo
const int pingPin = 7;

int incrServo = 1;
int posServo = 0;
int nextIncrServo = 0;
int button = 2;
int state = 0;

void setup() {
 
  Serial.begin(9600);
  myservo.attach(6);  // attaches the servo on pin 6 to the servo object
  pinMode(button, INPUT); // button on pin 2
}

void loop()
{
   int state = digitalRead(button);
   if (state == HIGH) {

   rodaServo();
   pingSensor();
   }
}

void rodaServo() {
   if(nextIncrServo <= millis()) {
      if(posServo <= 0 || posServo >= 180) incrServo *= -1;
      posServo += incrServo;
      myservo.write(posServo);
      nextIncrServo = millis() + 15;
    }
}

void pingSensor(){

 long duration, inches, cm;

  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);

  pinMode(pingPin, INPUT);
  duration = pulseIn(pingPin, HIGH);

  inches = microsecondsToInches(duration);
  cm = microsecondsToCentimeters(duration);
 
  Serial.print(inches);
  Serial.print("in, ");
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();
 
  delay(100); 
}


long microsecondsToInches(long microseconds)
{
  return microseconds / 74 / 2;
}

long microsecondsToCentimeters(long microseconds)
{
  return microseconds / 29 / 2;
}

Eldio Santos Jr.

unread,
Nov 29, 2011, 7:00:12 AM11/29/11
to ardu...@googlegroups.com
Antes de qualquer coisa, alguém sabe me dizer se a resposta do sensor fica "esperando" ser coletada pelo Arduino ou se tem a possibilidade de o Arduino proceder como procede com a serial (se houver algo ele lê, caso contrário ele retorna -1 e segue em frente)? Será que esse problema de leitura não pode ser porque devido ao código executado ele pode estar perdendo a resposta do sensor? Ou estou viajando demais e isso não tem nada a ver?

________________
Eldio Santos Junior
Tel.: (21) 8884-3757
Skype: eldiojr
Twitter: @eldius


Em 29 de novembro de 2011 09:55, Paulo Ferreira <paulofs...@gmail.com> escreveu:

Fernando Oliveira

unread,
Nov 29, 2011, 7:09:36 AM11/29/11
to ardu...@googlegroups.com
Tenta o seguinte:

Em 29 de novembro de 2011 09:59, Paulo Ferreira <paulofs...@gmail.com> escreveu:
#include <Servo.h>

Servo myservo;  // create servo object to control a servo
const int pingPin = 7;

int incrServo = -1;
  //delay(100); 
}


long microsecondsToInches(long microseconds)
{
  return microseconds / 74 / 2;
}

long microsecondsToCentimeters(long microseconds)
{
  return microseconds / 29 / 2;
}


Vou ver se acho mais alguma coisa...
 

Paulo Ferreira

unread,
Nov 29, 2011, 7:27:10 AM11/29/11
to ardu...@googlegroups.com
Fernando, aconteceu o seguinte, ele ainda está perdendo o sinal do ultrassonico e ainda está lento.

Victor Cinaglia

unread,
Nov 29, 2011, 7:37:48 AM11/29/11
to ardu...@googlegroups.com
Paulo, espero não desviar muito do foco da conversa, gostaria de saber onde comprou as rodas e o chassi do robô, parecem ser muito bons. Você está usando um servo motor para as rodas? Obrigado.

2011/11/29 Paulo Ferreira <paulofs...@gmail.com>

Eldio Santos Jr.

unread,
Nov 29, 2011, 7:41:47 AM11/29/11
to ardu...@googlegroups.com
Paulo, a questão da lentidão seria você variar a posição de forma diferente... Já quanto a estar perdendo o sinal... Você sabe me dizer qual a "resposta padrão" dele (o que ele retorna se ainda não tiver o intervalo)? Se souber tente incluir um laço pra só deixar ele sair quando a resposta for diferente dessa, algo como:

do{
            duration = pulseIn(pingPin, HIGH);
} while (duration != defaultValue);


Ou melhor, acabei de lembrar de ter visto isso em algum lugar...
Veja se isso aqui te ajuda:

________________
Eldio Santos Junior
Tel.: (21) 8884-3757
Skype: eldiojr
Twitter: @eldius


Paulo Ferreira

unread,
Nov 29, 2011, 7:43:26 AM11/29/11
to ardu...@googlegroups.com
Victor, eu comprei o kit completo da boe-bot e ele vem com o servo sim. Olha aí o link http://www.robotshop.com/productinfo.aspx?pc=RB-Plx-119&lang=en-US

Paulo Ferreira

unread,
Nov 29, 2011, 7:50:14 AM11/29/11
to ardu...@googlegroups.com
Pelo pouco conhecimento que eu tenho, eu acho que ele interrompe o sinal porque fica alternando entre o servo e o sensor, por exemplo, o servo anda 1 grau para direita e o sensor dá um ping, no momento que o servo andar mais 1 grau se o sensor tentar pingar e tiver processando o servo ele dá o resultado como 0. É como se eles não trabalhassem paralelamente. Eu vou dá uma saída, e a tarde estarei de volta. Vamos ver se resolvemos isso. Um abraço a todos.

Fernando Oliveira

unread,
Nov 29, 2011, 7:51:48 AM11/29/11
to ardu...@googlegroups.com
ele não faz em paralelo...


Just another Perl Hacker,
Fernando (SmokeMachine)
sip:f...@pbxes.org


Felipe Navarro

unread,
Nov 29, 2011, 8:06:40 AM11/29/11
to ardu...@googlegroups.com
Posso dar uma idéia?

Acho que dessa forma o qual vocês estão tentando fazer não vai funcionar.

Se ele girar ao mesmo tempo que emite o sinal a distância que ele ler vai estar incorreta.

Faz ele girar 5º e parar. Ler a distância, 5º pára lê a a distância e por ai vai.

Porque você precisa de precisão maior que 5º?

Abraços,
Felipe Navarro
--
Atenciosamente,
Felipe Navarro
Radioamador - PY1CX
www.felipenavarro.net

Wanderson Souza

unread,
Dec 19, 2011, 9:07:33 AM12/19/11
to ardu...@googlegroups.com
Estou desenterrando esse email, porque estou com um problema semelhante a do Paulo.

Fernando, tem como você me explicar essa estrutura que você fez?

void rodaServo() {
   if(nextIncrServo <= millis()) {
      if(posServo <= 0 || posServo >= 180) incrServo *= -1;
      posServo += incrServo;
      myservo.write(posServo);
      nextIncrServo = millis() + 15;
    }
}

E achei tb interessante a ideia de Felipe Navarro.

--
Mestrando Computação Distribuída - UFPB (Linha de Pesquisa - Robótica Cognitiva) 
Graduado em Licenciatura em Computação
Tecnólogo em Informática (Escola Técnica Redentorista)
MSN: wanders...@gmail.com
Twitter: twitter.com/wanderson_souza

Fernando Oliveira

unread,
Dec 19, 2011, 9:46:45 AM12/19/11
to ardu...@googlegroups.com




Just another Perl Hacker,
Fernando (SmokeMachine)


Em 19 de dezembro de 2011 12:07, Wanderson Souza <wanders...@gmail.com> escreveu:
Estou desenterrando esse email, porque estou com um problema semelhante a do Paulo.

Fernando, tem como você me explicar essa estrutura que você fez?

void rodaServo() {
   if(nextIncrServo <= millis()) {                                         // se o tempo previamente setado p/ o proximo incremento for maior ou igual ao tempo atual
      if(posServo <= 0 || posServo >= 180) incrServo *= -1;  // se a posicao do servo estiver fora do range válido, incrServo muda de sinal
      posServo += incrServo;                                            // incrementa
      myservo.write(posServo);                                         // escreve
      nextIncrServo = millis() + 15;                                    // seta o proximo incremento para daqui a 15 usec
    }
}

Felipe Navarro

unread,
Dec 20, 2011, 6:23:11 PM12/20/11
to ardu...@googlegroups.com
/*
Rodar um sensor ultrasonico sobre um servo de 0 a 180º e escrever a distância na serial
Author: Felipe Navarro
Data: 20/12/2011
*/

#include "Ultrasonic.h"
#include "Servo.h"

int pos = 0;
int a;
Servo myservo;
Ultrasonic ultrasonic(12,11); //(Trigger, Echo)

void setup()
  {
  Serial.begin(9600);
  myservo.attach(10); //Pino do servo na porta digital de numero 9
  }
 
void loop()
  {
    for(pos=0; pos<180; pos+=1)
      {
        myservo.write(pos);
        delay(20);
        Serial.println(ultrasonic.Ranging(CM));
        delay(80);
      }
    for(pos=180; pos>=1; pos=-1)
      {
         myservo.write(pos);
         delay(20);
         Serial.println(ultrasonic.Ranging(CM));
         delay(80);
      }
  }


Abraços,
Felipe Navarro
PY1CX
Reply all
Reply to author
Forward
0 new messages