Control de Motores con Java PI4J en Raspberry Pi

El objetivo de este tutorial es aprender a controlar motores lineales (DC) mediante señales PWM en un Raspberry PI.

Como ejemplo concreto realizaremos una demostración de control sobre un motor Lego M-Motor del set Lego Power Functions con Pi4J.

Partimos de la información del tutorial anterior de PI4J
https://unpocodejava.wordpress.com/2013/08/08/pi4j-control-del-gpio-de-raspberry-pi-con-java/

 

Qué es PWM


Lo primero es saber que el conector GPIO del Pi no tiene salidas ni entradas analógicas. Esto significa que, al contrario que otras placas controladoras como el arduino, no puede regular el voltaje de los pines. El voltaje de los conectores GPIO es digital, por tanto solo acepta dos valores:

  • 0 (0V/false/low/inactivo)
  • 1 (5V/true/high/activo).

PWM se podría traducir como modulación por amplitud de pulso. Es una técnica para enviar información de control a un dispositivo mediante la duración de la señal en un periodo de tiempo. Habitualmente se usa para controlar la potencia de motores, el ángulo de giro de un servo, etc.

Podemos ver como ejemplo en el diagrama de abajo muestra señales de control típicas de un motor DC y su porcentaje de rendimiento:

 

Técnicas de control


Podemos encontrar diversas técnicas de control para escribir señales PWM en periféricos.

  • Acceso mediante fichero en la distribución occidentalis
  • Lectura/escritura de la dirección de memoria localizada en el modulo GPIO usando punteros en la distribución occidentalis.
  • Módulos de control de motores, a través del I2C u otros pines (pe http://www.piborg.com/picoborg)

  • Mediante software: Librerías WiringPi https://projects.drogon.net/raspberry-pi/
  • Mediante software java: Librerias Pi4J.

Nos centraremos en esta última.

 

Ingredientes


Vamos a hacer un ejemplo sencillo. Para hacer la prueba, aparte del pi, necesitamos:

  • Faja GPIO

  • Placa de Pruebas

  • Porta baterías 6V(encontré uno como éste en la parte de modelismo de la jugueteria poli)
  • Cables
  • Chip controlador de motores(yo tengo un SN754410NE y va muy bien, aunque suelen recomendar también el L293D, buscarlos en tiendas de electrónica)
  • Motor lineal (a mí me gusta el m-motor de Lego Power Functions http://ro-botica.com/es/tienda/Marca/LEGO/LEGO-Power-Functions/)

 

Chip Controlador de Motor


Un driver de motores nos permite controlar mediante señales PWM el voltaje de la salida, es decir la velocidad, de un motor.

Sus ventajas:

  • Podemos controlar un voltaje de salida independiente del producido por el raspberry. La salida oficial del m-motor debería ser de 9V.
  • Podemos controlar el sentido de la corriente del motor dc, es decir giro del eje a la derecha o a la izquierda.
  • Podemos controlar hasta 2 motores con un solo chip.


Explicamos los pines imprescindibles para controlar un motor:

  • Pin 1 activa el motor 1 (lado izquierdo) cuando es true
  • Pin 2 entrada de control PWM del Pi giro a la derecha (en este caso pin 7 debe ser false)
  • Pin 3 salida motor 1 (cable motor 1)
  • Pin 4 tierra
  • Pin 5 tierra
  • Pin 6 salida motor 1(cable motor 2)
  • Pin 7 salida de control PWM del Pi giro a la izquierda (en este caso pin 2 debe ser false)
  • Pin 8 entrada voltaje del motor 1 (9V)
  • Pin 16 entrada voltaje controlador del chip (5V)
  • Pin 13 tierra
  • Pin 12 tierra

 

Preparar el motor


Para no romper la faja del motor, nos haremos con un alargador del lego power functions (8886 extension wire )

Unos pines, estaño, soldador, tubo termoretractil y procedemos a pelar los dos cables centrales y soldar los pines así:

 

Configuración


Y conectamos todo de esta manera

Cuando mandamos señales PWM a las salidas RaspiPin.GPIO_07 y RaspiPin.GPIO_00 del PI, controlaremos la dirección de giro y la velocidad del motor.

 

Ejemplo de Programa PI4J


Desde los pines 7 y 0 podemos controlar la velocidad e intensidad del motor. El pin GPIO_01 debe estar encendido (high), dado que define el “enabled” del controlador.


import com.pi4j.wiringpi.SoftPwm;
import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalOutput;
import com.pi4j.io.gpio.PinState;
import com.pi4j.io.gpio.RaspiPin;
import com.pi4j.io.gpio.GpioPinDigitalOutput;

public class ServoTest2 {
    
    public static void main( String[] args ) throws InterruptedException {
    	System.out.println( "-->start" );
        // initialize wiringPi library
        com.pi4j.wiringpi.Gpio.wiringPiSetup();
	final GpioController gpio = GpioFactory.getInstance();

        // crear pines pwm por software (id pin, min=0 ; max=100)
        SoftPwm.softPwmCreate( 7, 0, 100 );
	SoftPwm.softPwmCreate( 0, 0, 100 );
        // Este sera el pin “enabled” del controlador para el motor 1 
	GpioPinDigitalOutput pin = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_01);
	// enabled
	pin.high();

        
	int count = 10;
	while ( count-- > 0 ) {
		// motor a la derecha al 36%
		System.out.println( "-->36" );
		SoftPwm.softPwmWrite( 7, 36 );
		Thread.sleep( 1000 );

		// motor a la derecha al 96%
		System.out.println( "-->96" );
		SoftPwm.softPwmWrite( 7, 96 );
		Thread.sleep( 1000 );
		
		// motor a la derecha al 60%
		System.out.println( "-->60" );
		SoftPwm.softPwmWrite( 7, 60 );
		Thread.sleep( 1000 );

		// para motor derecha
		System.out.println( "-->0" );
                SoftPwm.softPwmWrite( 7, 0 );
                Thread.sleep( 1000 );

		// como motor derecha = false/0/low, activa motor izquierda 36%
                System.out.println( "-->36" );
                SoftPwm.softPwmWrite( 0, 36 );
                Thread.sleep( 1000 );
		
		// motor izquierda 96%
                System.out.println( "-->96" );
                SoftPwm.softPwmWrite( 0, 96 );
                Thread.sleep( 1000 );

		// motor izquierda 60%
                System.out.println( "-->60" );
                SoftPwm.softPwmWrite( 0, 60 );
                Thread.sleep( 1000 );

		// parar motor izquierda
                System.out.println( "-->0" );
                SoftPwm.softPwmWrite( 0, 0 );
                Thread.sleep( 1000 ); 
 
	}
        // disable motor 1
	pin.low();
    }
}

Conviene destacar para esta prueba que el motor de lego acepta 9V y nosotros lo alimentaremos con una batería de 6V, con lo cual no alcanzaremos el máximo potencial.

 

Referencias


http://pi4j.com
https://projects.drogon.net/raspberry-pi/wiringpi/
https://sites.google.com/site/semilleroadt/raspberry-pi-tutorials/gpio
http://www.dexterindustries.com/howto/lego-mindstorms-motors-with-raspberry-pi-brickpi-0-1/

Respuestas

  1. Muy buena guía, estoy pensando en hacer un pequeño robot con la raspberry pi, pero me están surgiendo unos cuantos problemas:
    -Necesito trabajar con 8 motores.(en realidad podría reducirlo a controlar 4, ya que trabajan por parejas)
    -Tengo dudas acerca de cual es el mejor so para usar en este proyecto(La programación sera en java)
    -Controlar la placa mediante otro dispositivo(seguramente sera android) mediante wifi, sin usar conexion a internet.

    1. – Efectivamente, con 8 motores reducidos a 4 necesitarias 2 chips controladores (cada uno controla una pareja), o una placa como la de http://www.piborg.com/picoborg q controlara los 4.
      – Si vas a programar en java el raspberry pi, beaglebone o placas similares (con un so debian o derivado) dan buenos resultados.
      – Cuando dices que no quieres pasar por internet entiendo que quieres controlar la placa en remoto directamente, sin utilizar un broker de mensajeria intermedio (como si fuera un mando a distancia). Como solución sencilla optaría por configurar la wifi del pi en modo access point
      https://learn.adafruit.com/setting-up-a-raspberry-pi-as-a-wifi-access-point/overview
      Conectate con el dispositivo android a la wifi del pi y mandale mensajes directamente con tu protocolo favorito (http, mqtt, websockets). En el raspbery tendrás que montar un servicio (java) que acepte e interprete las señales.

Deja un comentario