martes, 6 de octubre de 2015

Moviendo desvíos con servos y Arduino

Servo Tower Pro 9GBuenas a todos y todas los amantes de Arduino!!!

Después de estar mirando como poder mover los desvíos de mi nueva maqueta (aun en construcción) y viendo los precios y los diferentes sistemas (electroimanes, relés, motores caseros, etc..) me he decantado por los servos de modelismo y Arduino.

Lo que más me ha convencido son su bajo precio y lo fácil que son de instalar, si a eso le añadimos una placa Arduino, la cosa se hace mucho más interesante.

Ya no es que solo podamos mover el servo con Arduino, sino que también podremos tener salidas para poder conectar semáforos o cualquier otra cosa que queramos como los corazones de los desvíos.

Servo Tower Pro 9G:


Y la placa de Arduino que he elegido para este proyecto es la Arduino NANO con un shield especial (o ideal) para este proyecto:


Arduino Nano
Arduino Nano

Shield Arduino Nano
Shield Arduino Nano

🛠️ Componentes necesarios
Placa de Desarrollo NANO
Placa de Desarrollo NANO. Placa de Desarrollo NANO.
Servo Digital SG90 de 9g RC.
Servo Digital SG90 de 9g para RC." Servo Digital SG90 de 9g RC.
Shield S/E prototipo de expansión para Nano V3.0
Shield S/E prototipo de expansión para Nano V3.0 Shield S/E prototipo de expansión para Nano V3.0.

Además el precio es más que asequible, en total las dos placas tienen un coste menor de 8€.

En este caso, al no ir conectadas a ninguna central DCC, he tenido que construir un pequeño panel donde van 4 pulsadores y conectarlos a una entrada analógica.

Si, se podrían haber conectado a pines digitales pero he preferido hacerlo de manera analógica sobre todo por el tema del cableado y por que así me sobran otros tantos pines para una posible ampliación o conectar cualquier otra cosa que se me ocurra, pero eso sera cuando este la maqueta más avanzada. En principio se quedara tal y como se ve en el vídeo.

Los 4 pines asignados a los servos son el 6, 7, 8 y 9 y los 4 pines asignados a accesorios son el 10, 11, 12, 13.

Los pulsadores van conectados en el pin A0 con 5 resistencias de 1K. Luego leeremos estos valores con la función analogRead().


Lectura de pulsadores

La técnica se llama divisor de tensión con resistencias.
En lugar de usar un pin digital por cada pulsador, conectamos los cuatro pulsadores a un único pin analógico ADC. Cada pulsador, al ser presionado, genera un voltaje diferente y único, que el NANO puede leer y distinguir.

El ADC del Arduino Nano (ATMega328P) devuelve valores de 0 a 1023, lo que nos da una resolución de aproximadamente 4.88 mV por unidad (5V / 1023) o lo que es lo mismo 10bits de resolución.


  // Valor de la entrada analógica A0
  int valorPulsador = analogRead(0); 
  
  if (valorPulsador > 600 && valorPulsador < 1023)
  {
    Serial.println("S1");
  }
  else if (valorPulsador > 400 && valorPulsador < 600)
  {
    Serial.println("S2");
  }
  else if (valorPulsador > 300 && valorPulsador < 400)
  {
    Serial.println("S3");
  }
  else if (valorPulsador > 200 && valorPulsador < 300)
  {
    Serial.println("S4");
  }
  • S1: 4kΩ -> entre 600 y 1023
  • S2: 3kΩ -> entre 400 y 600
  • S3: 2kΩ -> entre 300 y 400
  • S4: 1kΩ -> entre 200 y 300
  • Ningún pulsador presionado: El pin ADC se queda a 0V, la lectura ADC ≈ 0

Conexión pulsadores en una protoboard


Servo desvíos arduino UNO
Conexión de los pulsadores a Arduino

Pulsadores

Arduino + Shield y servos


Código para mover servos con pulsadores

Aquí está el código con el que leemos los botones con la función analogRead() en A0 para controlar 4 servos en una maqueta a escala H0 o N:


/* Programa final para mover los desvíos de una maqueta mediante
 * servos de modelismo. 
 * Se utilizan 4 pulsadores conectados al pin analógico A0. 
 * Los pines reservados para los servos son: pin 6,7,8,9
 * y van enlazados a los pines 10,11,12,13 respectivamente para encender
 * un LED o accionar un rele 
 */

#include "Servo.h"

Servo servo1;       // Primer servo
Servo servo2;       // Segundo servo
Servo servo3;       // Tercer servo
Servo servo4;       // Cuarto servo 
int swcs = 0;

int estadoPos1 = 1;    // Estado posición servo1
int estadoPos2 = 1;    // Estado posición servo2
int estadoPos3 = 1;    // Estado posición servo3
int estadoPos4 = 0;    // Estado posición servo4

int servoVar1 = 70;    // Posición del servo1 al iniciar el programa
int servoVar2 = 70;    // Posición del servo2 al iniciar el programa
int servoVar3 = 70;    // Posición del servo3 al iniciar el programa
int servoVar4 = 95;    // Posición del servo4 al iniciar el programa

int servoVarMin1 = 70;  // Valor mínimo del servo1
int servoVarMin2 = 70;  // Valor mínimo del servo2
int servoVarMin3 = 70;  // Valor mínimo del servo3  
int servoVarMin4 = 65;  // Valor mínimo del servo4

int servoVarMax1 = 95;  // Valor máximo del servo1
int servoVarMax2 = 95;  // Valor máximo del servo2
int servoVarMax3 = 95;  // Valor máximo del servo3
int servoVarMax4 = 95;  // Valor máximo del servo4

int timeDelay = 50; 	// 90

int Led1 = 10;  // LED en pin 10 para servo1
int Led2 = 11;  // LED en pin 11 para servo2
int Led3 = 12;  // LED en pin 12 para servo3
int Led4 = 13;  // LED en pin 13 para servo4

void setup() 
{
  Serial.begin(115200);
  
  servo1.attach(6);    // Adjuntamos el pin 6 a servo1
  servo2.attach(7);    // Adjuntamos el pin 7 a servo2
  servo3.attach(8);    // Adjuntamos el pin 8 a servo3
  servo4.attach(9);    // Adjuntamos el pin 9 a servo4
  delay (150);
  
  servo1.write(servoVar1); 
  servo2.write(servoVar2); 	
  servo3.write(servoVar3);
  servo4.write(servoVar4);
  delay (150);
  
  servo1.detach();
  servo2.detach();
  servo3.detach();
  servo4.detach();
  
  pinMode(Led1,OUTPUT);
  pinMode(Led2,OUTPUT);
  pinMode(Led3,OUTPUT);
  pinMode(Led4,OUTPUT); 
}

void loop() 
{
  // Valor de la entrada analógica A0
  int valorPulsador = analogRead(0); 
  
  if (valorPulsador > 600 && valorPulsador < 1000)
  {
    swcs = 1;
    Serial.println("S1");
    Serial.println(valorPulsador);
  }
  
  if (valorPulsador > 400 && valorPulsador < 600)
  {
    swcs = 2;
    Serial.println("S2");
    Serial.println(valorPulsador);
  }

  if (valorPulsador > 300 && valorPulsador < 400)
  {
    swcs = 3;
    Serial.println("S3");
    Serial.println(valorPulsador);
  }
  
  if (valorPulsador > 200 && valorPulsador < 300)
  {
    swcs = 4;
    Serial.println("S4");
    Serial.println(valorPulsador);
  }
  
  
  switch (swcs)
  {
    // Movimiento Servo 1 
    case 1:
      servo1.attach(6);    // Adjuntamos el pin 6 a servo1 
      if (estadoPos1 == 1) 
      {
        for(servoVar1 = servoVarMin1; servoVar1 <= servoVarMax1; servoVar1 += 1)
        {
          servo1.write(servoVar1);
          delay(timeDelay);
          // Serial.print (servoVar2);
          // Serial.print (", "); 
    	}    
    	estadoPos1 = 0;
    	swcs = 0;
        digitalWrite (Led1, HIGH);
        delay (50);
      } 
      else 
      {
        if (estadoPos1 == 0)
        {
          for(servoVar1 = servoVarMax1; servoVar1 >= servoVarMin1; servoVar1 -= 1)
          {
            servo1.write(servoVar1);
            delay(timeDelay);
            // Serial.print (servoVar2);
            // Serial.print (", ");
            estadoPos1 = 1;
            swcs = 0;
            digitalWrite (Led1, LOW);
            delay (50);
          }
        }
        servo1.detach();
        break;
   
    // Movimiento Servo 2
    case 2:
      servo2.attach(7);    // Adjuntamos el pin 6 a servo1
      if (estadoPos2 == 1) 
      {
        for(servoVar2 = servoVarMin2; servoVar2 <= servoVarMax2; servoVar2 += 1)
        {
          servo2.write(servoVar2);
          delay(timeDelay);
          // Serial.print (servoVar2);
          // Serial.print (", "); 
        }
        estadoPos2 = 0;
    	swcs = 0;
        digitalWrite(Led2, HIGH);
        delay(50);
      }
      else
      {
        if (estadoPos2 == 0)
        {
          for(servoVar2 = servoVarMax2; servoVar2 >= servoVarMin2; servoVar2 -= 1)
          {
            servo2.write(servoVar2);
            delay(timeDelay); 
			// Serial.print (servoVar2);
            // Serial.print (", ");
          }
          estadoPos2 = 1;
          swcs = 0;
          digitalWrite(Led2, LOW);
          delay(50);
        }
      }
      servo2.detach();
      break;
      
  // Movimiento Servo 3
	case 3: 
      servo3.attach(8);    // Adjuntamos el pin 8 a servo3
      if (estadoPos3 == 1) 
      {
        for(servoVar3 = servoVarMin3; servoVar3 <= servoVarMax3; servoVar3 += 1)
        {  
          servo3.write(servoVar3);
          delay(timeDelay); 
          // Serial.print(servoVar3);
          // Serial.print (", ");
        }
        estadoPos3 = 0;
        swcs = 0;
        digitalWrite (Led3, HIGH);    
    	delay (50);
      } 
      else 
      {
        if (estadoPos3 == 0)
        {
          servo3.attach(8);    // Adjuntamos el pin 8 a servo3
          for(servoVar3 = servoVarMax3; servoVar3 >= servoVarMin3; servoVar3 -= 1)
          {
            servo3.write(servoVar3);
            delay(timeDelay); 
            // Serial.print (servoVar3);
            // Serial.print (", ");
          }
          estadoPos3 = 1;
          swcs = 0;
          digitalWrite(Led3, LOW);
          delay(50);
        }
      }
      servo3.detach();
      break;
  
  // Movimiento Servo 4
    case 4: 
      servo4.attach(9);    // Adjuntamos el pin 9 a servo4
      if (estadoPos4 == 1) 
      {
        for(servoVar4 = servoVarMin4; servoVar4 <= servoVarMax4; servoVar4 += 1)
        {
          servo4.write(servoVar4);
          delay(timeDelay); 
          // Serial.print (servoVar4);
          // Serial.print (", ");
        }
        estadoPos4 = 0;
        swcs = 0;
        digitalWrite(Led4, HIGH);
        delay(50);
      } 
      else 
      {
        if (estadoPos4 == 0)
        {
          for(servoVar4 = servoVarMax4; servoVar4 >= servoVarMin4; servoVar4 -= 1)
          {
            servo4.write(servoVar4);
            delay(timeDelay);
            // Serial.print (servoVar4);
            // Serial.print (", ");
          }
          estadoPos4 = 1;
          swcs = 0;
          digitalWrite(Led4, LOW);
          delay(50);
        }
      }
      servo4.detach();
      break;
	}
    /*
    delay(500);
	Serial.println("");	
	Serial.print(estadoPos1);
	Serial.print(", ");
	Serial.print(estadoPos2);
	Serial.print(", ");
	Serial.print(estadoPos3);
	Serial.print(", ");
	Serial.print(estadoPos4);
    */
}


Si te ha gustado el articulo puedes o quieres ver más proyectos con servos y Arduino, aquí tienes una lista de otros ejemplos que puedes visitar:

Saludos a todos y todas!!

26 comentarios :

Unknown dijo...

Hola:Me parece muy interesante tu circuito. estoy intentando hacer lo mismo en mi maqueta pero no encuentro los valores de las resistencias que has colocado. Con las que yo estoy colocando no me funciona bien.
Un saludo y gracias

Peyutron dijo...

Buenas Alberto, las resistencias son de 1K (1000ohm) y tienen que tener todas el mismo valor, si no, no funcionara. Espero te ayude, Saludos!!!

Unknown dijo...

muchas gracias, mañana me las compro y lo pruebo.
un saludo

Unknown dijo...

Hola ya tengo todo montado tal y como pone aquí en este manual, pero tengo un problema, solo me funcionan dos servos, y uno funciona con dos pulsadores, el mismo servo actúa al pulsar tanto un pulsador como con otro, sabes de qué puede ser, a ver si me podéis ayudar, y ante todo muchas gracias por el trabajo que hacéis,

Peyutron dijo...

Buenas Tomovil Ford! ¿Has puesto el mismo número de pulsadores? en caso de que sea que si, ¿has comprobado las resistencias? en el programa viene un pequeño debug para comprobar en el monitor serie del IDE de Arduino (Ctrl+Mayus+M), en el te dirá el valor de cada pulsador y en función a esto puedes ajustar un poco mas los valores con respecto al servo. Espero haberte ayudado y si tu problema persiste, puedes mandarme una captura de pantalla del monitor serie a mi correo peyutron@gmail.com. Saludos!!!

Unknown dijo...

Gracias. Peyutron , probaré lo que me dices, y te comentaré, bueno a ver si me entero bien, por qué estos verde en este tema, jeje, Mubchas gracias

Anónimo dijo...

Está muy buena tu publicación y gracias por compartirla. Llevo mas de un año buscando información de cómo accionar servos con un pulsador. Una consulta, teniendo libres los pines 0 al 5, se podrá poner mas servos por placa? Esto con el fin de comprar menos placas solamente y ahorrar un poco.
Reitero mis agradecimientos

Anónimo dijo...

Otra consulta, el código funciona en una placa Arduino Uno?

Peyutron dijo...

Buenas! Si, no hay problema en usar esos pines, aunque te aconsejaría que el 0 y el 1 no los usará ya que puede dar problemas al cargar el sketch ya que son los pines que utiliza arduino para comunicarse con el PC, Saludos!!!!

Peyutron dijo...

Buenas! En principio tiene que funcionar, de echo las pruebas las hice con UNO. Si te diera alguna error comentamelo y vemos la solución. Pero en principio tendría que ir bien. Saludos!!!

Anónimo dijo...

Hola, me he demorado un poco en poner en práctica tu aporte pero ya empecé. El fin de semana pasado lo monté en la protoboard con el Arduino UNO R3 y me dio varios errores. Uno de ellos es que los servos no van de un lado a otro conforme se presiona el pulsador sino que van y vuelven de inmediato a su posición original. Por otro lado, los LED no prenden de acuerdo al pulsador accionado sino que es un tanto aleatorio. Revisé una y mil veces las conexiones y creo que están bien. La fuente de energía para los servos la tuve que poner en forma independiente (no desde la misma placa) porque si lo hacía al parecer hacía corto circuito y suspendía la placa. Voy a hacer un esquema en Fritzing de las conexiones y lo subo. Saludos

chuko72 dijo...

hola, este montaje es justo lo que busco aunque pretendo mover 8 desvios. en el caso de hacerlo con arduino uno, como conectas los servos? por otro lado, los pulsadores como los has conectado?
un saludo y gracias por adelantado

Anónimo dijo...

Hola, me gustaría saber si los servos también se podrían controlar mediante interruptores y no botones. Muchas gracias por la ayuda.

Unknown dijo...

Hola, me gustaría saber si los servos también se podrían controlar mediante interruptores y no botones. Muchas gracias por la ayuda.

Peyutron dijo...

Buenas Raúl, aquí tienes un ejemplo de cómo aplicar interruptores: https://paletosdelaelectronica.wordpress.com/2016/02/07/usando-un-interruptor-con-arduino sólo tendras que cambiar un par de cosas y funcionará. Saludos!!!

Unknown dijo...

Muchas graciasss!!!

Unknown dijo...

Y en el caso de que se tratará de conmutadores, ¿sería el mismo esquema que el tuyo con los botones?

Peyutron dijo...

Buenas, no sirve para interruptores porque utilizo el puerto analógico para leer los pulsadores. Para poner interruptores tendrías que usar un pin digital por interruptor. Saludos!

Unknown dijo...

He visto en la foto de el circuito que ha compartido arriba que desde la placa hacia los pulsadores hay 3 cables, ¿el verde hacia donde va? Perdón por mi pesadez, jajajja

Peyutron dijo...

Imagino que te refieres al gris, este va al puerto analógico, con la suma de resistencias hace que cada pulsador tenga un valor fijo, es como tener un potenciómetro, pero que no varía. Si te refieres a las líneas líneas que se ven como más apagadas son las que crea fritzing para que se vea cómo van las conexiones dentro de la placa de pruebas, no pasa nada, no hay que quedarse con la duda, saludos!!!

chuko72 dijo...

hola, perdonad si me meto por medio pero tengo una duda, solo necesitas un pin analógico para los 4 pulsadores? si no usas las resistencias funciona?
un saludo y gracias de antemano

Peyutron dijo...

Buenas chuko72,sin resistencias el pin analógico solo leerá un pin al aire pero al ir sumando resistencias tienes siempreun valor fijo, saludos!!!

chuko72 dijo...

hola Peyutron, muchas gracias por responder. aclaradas las resistencias. la otra duda, un solo pin para los 4 servos? otra cosa, en el esquema, las lineas violetas son puentes entre los pulsadores?
gracias por adelantado y perdona tanta pregunta pero es que me interesa mucho tu montaje y tengo muy pocos conocimientos de arduino

Peyutron dijo...

Buenas chuko72, un solo pin (y analógico) para los pulsadores, los servos cada uno a un pin. Las líneas violeta son puentes entre pulsadores para que la resistencia que va "sola" tenga contacto con todos los pulsadores. Saludos!!!

chuko72 dijo...

Muchas gracias por la aclaración. Por último, se pueden usar más servos y valdría la nano? Cambia el valor de las resistencias?
Nuevamente gracias por adelantado

chuko72 dijo...

hola Peyutron, pudiste ver si es posible usar hasta 8 servos con la nano?
un saludo