arduino y servos

Hola intento controlar un servo con un simple programa pero no funciona nada ¿ Me podeis echar un cable ?
gracias

int ain=0;//pot 10k conectado al pin 0
int pwmpin=3;//servo conectado al pin nº3
int aval=0;

void setup(){
pinMode(pwmpin,OUTPUT);
}
void loop(){
analogRead(ain);
if (ain>500)
digitalWrite(pwmpin,2000);//mueve el servo a la derecha
if (ain<500)
digitalWrite(pwmpin,1000);//mueve el servo a la izquierda
if (ain==500)
digitalWrite(pwmpin,1500);//mueve el servo al centro
delay(20);
}

Hola,

¿Puedes mandar algo más de información? … modelo del servo, características, una foto del circuito para ver las conexiones que haces, etc …

Salu2,

Igor

El servo es de los utilizados en modelismo y en el pin nº 3 , conecto el cable de señal , y pretendo hecer salir un pulso pwm entre 1000 y 2000 microsegundos para controlar el servo o 1500 microsegundos para el neutro

Hola,

Creo que el error es que sólo puedes escribir un valor entre 0 y 1023 para simular un voltaje de salida de entre 0 y 5 V. Por eso estaría ver bien saber el modelo del servo para ver con qué voltaje trabaja.

Un saludo,

Igor

Y más ... que estoy despistado ... analogWrite() ... es la que genera PWM.

Salu2,

Igor

El servo funciona a 5V y para controlarlo necesitamos una señal pwm entre 1000 y 2000 microsegundos ó entre 1y2 milisegundos

Perdón ... no suelo usar PWM ... y estoy en las nubes.

  • analogRead(int pin) devuelve valores entre 0 y 1023 (de 0 a 5 V).
  • analogWrite(int pin, int value) sólo acepta valores entre 0 y 255 (de 0 a 5 V).

Además tienes que tener en cuenta que si el chip de tu placa es un:

  • atmega8 --> Puedes utililizar los pines digitales 9, 10 y 11 para generar PWM . atmega168 --> Puedes utililizar los pines digitales 3, 5, 6, 9, 10 y 11 para generar PWM

Más info: http://www.arduino.cc/en/Reference/AnalogWrite

No me sé la relación exacta entre la frecuencia y el voltaje generado (de 0 a 5 V) mediante analogWrite().

Si lo que quieres es generar PWM modulando tú mismo la señal digital a través de cualquier pin digital no lo puedes hacer mediante el código que has mandado. Tendrías que hacer un bucle con un delay los ms que necesites. Por ejemplo

while ("condición") {
  digitalWrite(3, HIGH);
  delay(1);                      
  digitalWrite(3, LOW);
  delay(1);
}

Salu2,

Igor

Más info sobre el PWM:

http://www.arduino.cc/es/AnalogWrite/PWM

Salu2,

Igor

Gracias Igor , voy a probar y en cuanto lo consiga lo posteo por aquí , estaba a punto de pasarme a usar un picaxe 28x que tiene tambien entradas analogicas y tiene un comando pwm directo a un pin de salida

Saludos

Arduino sí tiene comando para escribir PWM directamente ... analogWrite(int pin, int value). Sólo tienes que calcular el escalado que relaciona valor y voltaje generado.

0 --> 0 voltios ... 127 --> 2,5 voltios ... 255 --> 5 voltios

Al final, lo importante del PWM es el voltaje generado ... no la frecuencia con la que hacerlo. Sigo pensando que hablamos de lo mismo, pero con palabras distintas.

Es tan fácil como leer la datasheet del servomotor para ver como funciona tu servomotor. No tengo ni idea de aeromodelismo ni de los motores que se utilizan para aeromodelismo.

No te recomiendo controlar PWM modulando tú mismo la señal digital con delays ... es complicadillo.

Salu2,

Igor

Hola Igor he encontrado esto por ahí

int servoPin = 3; // Control pin for servo motor int minPulse = 900; // Minimum servo position int maxPulse = 2100; // Maximum servo position int pulse = 0; // Amount to pulse the servo

int refreshTime = 18; // the time needed in between pulses

int analogValue = 0; // the value returned from the analog sensor int analogPin = 0; // the analog pin that the sensor's on

void setup() { pinMode(servoPin, OUTPUT); // Set servo pin as an output pin pulse = minPulse; // Set the motor position value to the minimum }

void loop() { analogValue = analogRead(analogPin); // read the analog input pulse = (((float)analogValue / (float)1023)*1200) + 900;

digitalWrite(servoPin, HIGH); // Turn the motor on delayMicroseconds(pulse); // Length of the pulse sets the motor position digitalWrite(servoPin, LOW); // Turn the motor off delay(refreshTime); } lo he probado y funciona bien ; se trata de un potenciometro conectado al pin 0 y en servo al pin 3 moviendo el pot de izqd. a drcha. el servo también lo hace

Ahora lo quiero modificar para conectar dos LDR en los pin 0 y 1 el programa compara las dos analog y mueve el servo hasta que las dos LDR se quedan compensadas

Bueno te explico mas : Es para un panel solar , debajo del panel hay un servo que lo hace mover 180º asi cuando sale el sol el panel lo apunta y no deja de hacerlo hasta que se pone , Las LDR van en el fondo de dos tubos de 3-4 cm y estos tubos van encima del panel separados unos 20 cm , de modo que si una LDR recibe mas luz que otra el servo se moverá para que las dos LDR reciban la misma cantidad de luz y por lo tanto el panel solar la maxima intensidad durante todo el recorrido del sol . Saludos

Hola Igor he escrito este programa , pero no me funciona ¿ me puedes orientar?
Gracias

int servoPin=3;//servo conectado al pin 3
int maxpulse=2000;//max retardo servo
int minpulse=1000;//min retardo servo
int ldr1in=0;//LDR al pin 0
int ldr2in=1;//LDR alpin 1
int ldr1val=0;
int ldr2val=0;
int movemode=0;
void setup(){
pinMode(3,OUTPUT);
digitalWrite(servoPin,HIGH);
delayMicroseconds(1500);//aqui se situa el servo en la posicion central
digitalWrite(servoPin,LOW);
}
void loop(){
ldr1val=analogRead(0);
ldr2val=analogRead(1);
}
if(ldr1val>ldr2val){
movemode=1;
}
if(ldr1val<ldr2val){
movemode=2;
}
if(movemode==1){//mueve el servo hacia un lado
digitalWrite(servoPin,HIGH);
delayMicroseconds(2000);
digitalWrite(servoPin,LOW);
}
if(movemode==2){//mueve el servo hacial el otro lado
digitalWrite(servoPin,HIGH);
delayMicroseconds(1000);
digitalWrite(servoPin,LOW);
}

Hola,

El problema podría ser que has cerrado el loop justo después de leer los valores analógicos, por lo que lo único que se repite en eso … los dos analogRead. El resto de código lo ignora. Te recomiendo que vayas anidando los parénteis cuando programes para evitar problemas de este tipo.

Pruebalo así …

int servoPin=3;//servo conectado al pin 3 
int maxpulse=2000;//max retardo servo 
int minpulse=1000;//min retardo servo 
int ldr1in=0;//LDR al pin 0 
int ldr2in=1;//LDR alpin 1 
int ldr1val=0; 
int ldr2val=0; 
int movemode=0; 
void setup(){ 
  pinMode(3,OUTPUT);   
  digitalWrite(servoPin,HIGH); 
  delayMicroseconds(1500);//aqui se situa el servo en la posicion central 
  digitalWrite(servoPin,LOW); 
} 
  void loop(){ 
  ldr1val=analogRead(0); 
  ldr2val=analogRead(1); 
//  sobra aquí ---> } 
  if(ldr1val>ldr2val){ 
    movemode=1; 
  } 
  if(ldr1val<ldr2val){ 
    movemode=2; 
  } 
  if(movemode==1){//mueve el servo hacia un lado 
    digitalWrite(servoPin,HIGH); 
    delayMicroseconds(2000); 
    digitalWrite(servoPin,LOW); 
  } 
  if(movemode==2){//mueve el servo hacial el otro lado 
    digitalWrite(servoPin,HIGH); 
    delayMicroseconds(1000); 
    digitalWrite(servoPin,LOW); 
  }
}  // fin del loop

En el primer ejemplo que has mandando, lo que hace el código es un escalado del rango de valores, por lo que al variar, varía la posición más o menos. Deberías hacer lo mismo. Si no lo que vas a conseguir es que vaya de un extremo al otro sin posiciones intermedias.

También sería buena idea poner un delay después de cada “digitalWrite(servoPin,LOW);” . El valor depende de las características del servo. Si con 18 te iba bien en el primer ejemplo … pruebalo en tu código.

Salu2,

Igor

Gracias Igor lo probaré ; de todas formas el servo lleva una reductora y gira despacio hasta que las dos LDR se igualan

Eso de que "se igualen" los valores es muy muy complicado ... mejor que habilites un rango de valores en el que consideres que el valor es similar. Por ejemplo ... si la diferencia entre ambos es menor que X ... considera que están igualados. Lo mejor es que calibres las LDR y veas cual es el valor máximo y mínimo que dan, y como varían los valores cuando la luz es más o menos estable.

Salu2,

Igor

Si , es verdad he montado directamente las dos ldr encima del servo y cuando las dos tienen luz igual , entonces el servo empieza a oscilar a un lado y a otro rapidamente , ¿ se puede programar algun filtro ? , o ¿ se puede introducir algun grado de histeresis ? . Saludos

int servoPin=3;//servo conectado al pin 3
int maxpulse=2000;//max retardo servo
int minpulse=1000;//min retardo servo
int ldr1in=0;//LDR al pin 0
int ldr2in=1;//LDR alpin 1
int ldr1val=0;
int ldr2val=0;
int movemode=0;
void setup(){
pinMode(3,OUTPUT);
digitalWrite(servoPin,HIGH);
delayMicroseconds(1500);//aqui se situa el servo en la posicion central
digitalWrite(servoPin,LOW);
delay(18);
}
void loop(){
ldr1val=analogRead(0);
ldr2val=analogRead(1);
if(ldr1val>ldr2val){
movemode=1;
}
if(ldr1val<ldr2val){
movemode=2;
}
if(ldr1val==ldr2val){
movemode=0;
}
if(movemode==0){//mueve el servo al centro
digitalWrite(servoPin,HIGH);
delayMicroseconds(1500);
digitalWrite(servoPin,LOW);
delay(18);
}
if(movemode==1){//mueve el servo hacia un lado
digitalWrite(servoPin,HIGH);
delayMicroseconds(2000);
digitalWrite(servoPin,LOW);
delay(18);
}
if(movemode==2){//mueve el servo hacial el otro lado
digitalWrite(servoPin,HIGH);
delayMicroseconds(1000);
digitalWrite(servoPin,LOW);
delay(18);
}
}

hola! soy nuevo en esto por lo que solicito su ayuda, es algo muy simple...

necesito controlar un motor servo, hacia la derecha y la izquierda, dandole velocidades que yo quiera. es para un proyecto de arte

los codigos expuestos aqui no me funcionan del todo bien porfavor necesito de su ayuda

una ves que tenga el codigo me gustaria saber como lo hago para manejar mas de 1 motor servo con el mismo arduino, onda para que cada motor tenga sus propios movimientos,, se puede? agradesco la ayuda y muchas gracias, tremendo aporte