Manejar un motor stepper con un driver DRV8825 y Arduino

Voy a contar cómo manejar un motor paso a paso (stepper) con Arduino a través de un controlador DRV8825. En esta otra entrada explico cómo hacerlo con una Raspberry Pi, de forma muy similar, y en esta hablo de varios motores y drivers.

0j42241200

Características principales del driver DRV8825:

  • Para motores bipolares
  • Permite microstepping de hasta 1/32
  • 1.5  por fase o 2.2A si se dispone de ventilación forzada de aire o disipadores
  • Interfaz casi idéntica al A4988
  • 45 V máximo
  • Control de corriente máxima con un potenciómetro

El motor que voy a usar es un motor NEMA 17 JK42HS40-1704 13A, comprado aquí por 12.50 €, pero valdría cualquier motor bipolar de 4 cables.

Características del motor:

  • Número de parte: JK42HS40-1704 13A
  • Tamaño de marco: NEMA17
  • Ángulo del paso: 1,8 grados
  • Voltaje: 3.4V
  • Corriente: 1,7 A/fase
  • Resistencia: 2,0 ohmios/fase
  • Inductancia: 3,0 mH/phase
  • Llevar a cabo el esfuerzo de torsión: 4000g-cm 58.30 OZ-IN
  • Inercia del rotor: 54 g-cm2
  • Esfuerzo de torsión de la muesca: 0,22 kilogramo-cm
  • Número de ventajas de alambre: 4
  • Peso: 0,24 kilogramos
  • Longitud: 40m m
  • Eje del motor: 5mm
  • Longitud del árbol delantero: 20 mm
  • Certificación: CE, ROHS, ISO9001

Para alimentar el motor empleo una fuente de alimentación de un ordenador (ver esta entrada).

Siguiendo las instrucciones de la página de Pololu, voy a emplear el siguiente modo de conexión, con paso completo (sin microstepping):

Empleo un Arduino Nano, pero valdría cualquier otro. Uso el pin 8 para la dirección y el 9 para el step. El esquema Fritzing de mi montaje es así:

Manejar un motor paso a paso con DRV8825 y Arduino

 

La conexión de los cables del motor al DRV8825 la hago así:

  • B2: azul
  • B1: rojo
  • A1: negro
  • A2: verde

Para no dañar el motor tenemos que regular inicialmente el potenciómetro a la mínima potencia, girando el potenciómetro en sentido antihorario hasta el final, y más adelante ajustarlo hasta la capacidad del motor. En este vídeo se explica cómo regular adecuadamente la intensidad, que cuento a continuación.

Empiezo con el motor desconectado. Lo primero, calculo el voltaje por cada fase. Para eso me fijo en las características de mi motor. Ahí me dicen que el motor es de 1.7 A / fase. Tendré que limitar el DRV8825 a este valor. Por encima de 1.5 A (y hasta 2.2A) el controlador DRV8825 debe tener ventilación forzada de aire o un disipador, así que le pego un disipador (me venía al comprarlo con el DRV8825), pues pretendo fijarlo en la capacidad máxima del motor.

Ahora tengo que ajustar la corriente del DRV8825 con el potenciómetro. Primero tengo que averiguar a cuánto he de limitar esa corriente. Para ello empleo la fórmula que viene en la hoja de especificaciones del driver:

Current Limit = VREF × 2

(Ojo, que por muchas páginas se ven otras fórmulas; hay que emplear la fórmula específica de nuestro driver).

Entonces:

1.7 = VREF x 2

VREF = 0.85 V

Pero ojo, este voltaje va asociado a la corriente máxima que recibirá el motor, y depende de la configuración de micropasos. Hay que consultar en la Tabla 2 de la hoja de especificaciones del DRV8825. En mi caso, con paso completo (full step), la corriente es un 71%, así que deberé multiplicar por este factor el resultado anterior:

VREF = 0.71 · 0.85 = 0.60 V

Así que el voltaje límite que debo ajustar es 0.60 V por fase.

Ahora tengo que ver dónde medir con el multímetro en el DRV8825:

Aunque es más fácil medir directamente desde el potenciómetro:

Desconecto el motor, pero alimento con 12V el DRV8825 y alimento también el Arduino a través del puerto USB. Con todo así, mido el voltaje y ajusto el potenciómetro hasta alcanzar mis VREF calculado antes (0.60 V).

Ya tengo el driver ajustado a mi motor, así que ya puedo conectarlo y empezar a utilizarlo.

Cargando el siguiente código a Arduino, el motor da una vuelta completa en una dirección, y luego cambia de dirección y da otra vuelta:

const int dirPin = 8;
const int stepPin = 9;
 
const int steps = 200;
int microPausa = 1000;
 
void setup() {
 pinMode(dirPin, OUTPUT);
 pinMode(stepPin, OUTPUT);
}
 
void loop() {
 digitalWrite(dirPin, HIGH);  // Establezco una dirección

 for (int x = 0; x < steps ; x++) {
   digitalWrite(stepPin, HIGH);
   delayMicroseconds(microPausa);
   digitalWrite(stepPin, LOW);
   delayMicroseconds(microPausa);
 }
 delay(1000);
 
 digitalWrite(dirPin, LOW);  // Cambio la dirección

 for (int x = 0; x < steps ; x++) {
   digitalWrite(stepPin, HIGH);
   delayMicroseconds(microPausa);
   digitalWrite(stepPin, LOW);
   delayMicroseconds(microPausa);
 }
 delay(1000);

}

 

Y un vídeo mostrando el motor en movimiento con el código anterior:

 

Referencias

https://www.pololu.com/product/2133

http://hetpro-store.com/TUTORIALES/controlador-de-motor-pasos-drv8825en-construccion/

http://www.luisllamas.es/2016/08/motores-paso-paso-arduino-driver-a4988-drv8825/

https://forum.pololu.com/t/drv-8825-stepper-motor-steps-and-delay-between-pulses/7530

Acceder a la consola de una Raspberry Pi (Zero) por UART con un adaptador USB PL2303

La Pi Zero es una maravilla, si no fuera por lo complicado que es acceder a su consola, al tener un único puerto USB y no tener ni WiFi integrado ni una conexión de red: hace falta conectarse con un teclado y a una pantalla a través de HDMI, o a través de un hub USB, más una tarjeta WiFi USB, etc.

Una forma más sencilla de poder acceder a la consola de la Raspberry Pi es a través de UART, con un cable específico USB, o con un adaptador USB PL2303. Esto es válido no solo para la Raspberry Pi Zero, sino para todas las Raspberrys.

Adaptador USB – TTL PL2303 (vista delantera)

Adaptador USB – TTL PL2303 (vista trasera)

Lo primero es activar la comunicación en serie en la Raspberry Pi. Esto lo podemos hacer con sudo raspi-config
y después en Advanced Options – Serial decimos sí a permitir hacer login por serie. Otra alternativa es editar el ficher /boot/config.txt y añadir al final enable_uart=1. En cualquier caso, es necesario reiniciar tras hacer el cambio.

Ahora es necesario instalar los drivers en nuestro ordenador para que reconozca el PL2303. Para ello nos descargamos de la página oficial el driver correspondiente a nuestro sistema operativo (para Mac, para Windows, para Linux no hace falta, viene por defecto). Tras instalarlo tenemos que reiniciar el ordenador.

Como en Windows me ha dado problemas (no reconoce el módulo), al final lo he probado desde mi Mac y ha funcionado. He hecho lo siguiente.

 

Tras instalar el driver del enlace anterior y reiniciar, he conectado el adaptador (a su vez conectado a la Raspberry Pi) de la siguiente forma:

Ojo, que el TXD de la Raspberry Pi se conecta al RXD del PL2303 y viceversa.

Esquema conexión PL2303 a Raspberry Pi Zero

Tras comprobar que todo estaba bien conectado, he abierto una consola en mi Mac y he escrito el siguiente comando: screen /dev/cu.usbserial 115200. ¡Y ya está! Tras hacer eso y dar al enter, ya nos pide el usuario y contraseña y ya estamos conectados a la Raspberry Pi.

(Ojo, que a lo mejor en otros casos el dispositivo podrá tener otro nombre; entonces bastará con teclear screen /dev/cu. y darle al TAB para ver los que hay, y escogemos.)

Diseño y construcción de un arpa láser

Introducción

Hace tiempo me encontré por internet una página en la que se explicaba cómo construirse un arpa láser casera. La idea es sencilla: se tiene un láser que encendemos y apagamos a muy alta velocidad contra un espejo montado sobre un motor a pasos que va cambiando de posición de forma sincronizada con el láser, de tal manera que por persistencia de la visión da lugar a una serie de haces de luz muy espectaculares, si el láser tiene la potencia adecuada y/o la luz ambiente es apropiada. Si disponemos una célula fotoeléctrica que detecte cuándo uno de los haces de láser ha sido interrumpido y vemos en qué posición está el láser en ese momento, podemos asociar a cada posición del láser una nota musical, que se envía por MIDI a un teclado o al ordenador, o podemos también hacer sonar con un pequeño altavoz.

Arpa láser en su configuración final

Arpa láser en su configuración final

Como además estaba preparando un concierto para unos meses más tarde en el que podría quedar muy bien hacer una parte con el arpa láser, decidí construirme una.

En esta página describo todo el proceso de montaje de un arpa láser plenamente funcional, tratando de explicar las pruebas que hice y todos los pasos que seguí, así como las referencias que consulté siempre que he podido. Ojo, que muchas de las páginas de internet sobre arpas láser no son del todo funcionales, o se quedan a la mitad y no lo llevan hasta el final, o directamente cuentan cosas que no son del todo creíbles.

Para llegar al arpa que empleé en el concierto, construí varios prototipos parciales y uno completo antes del arpa definitiva. Las fotos que pongo en la página pueden corresponder a alguno de los prototipos o a la definitiva en proceso de montaje.

Aviso al navegante: si tienes intención de hacer algo parecido a las arpas láser de Jean Michel Jarre ya puedes ir preparándote para un gran desembolso económico y para dedicarle mucho tiempo…

Y el aviso más importante, y no es broma: trabajar con láseres, especialmente de alta potencia como el que empleo en este arpa, supone un riesgo muy alto y existe la posibilidad de quedarse ciego si se mira accidentalmente al láser (o un reflejo de éste en alguna superficie reflectante) ya que puedes quemarte la retina en un tiempo menor del tiempo de reacción de cerrar el ojo o apartar la mirada. Así que hay que emplear en todo momento gafas protectoras, adecuadas al láser que empleemos, evitar que haya más gente donde estemos trabajando y ser muy cuidadoso…

Material y lista de la compra

General:

  • Cables (pueden ser normales o tipo Dupont)
  • Cola térmica
  • Soldador
  • Resistencias varias
  • Madera o caja de aproximadamente 32 x 20 cm

Opcional:

  • Teclado MIDI al que conectar el arpa láser y que genere los sonidos.
  • Interfaz MIDI – USB (4.86 €) sólo necesario si no disponemos de un sintetizador o teclado MIDI que genere los sonidos.
  • Conector DC 12 V 2.1 mm x 5.5 mm (3 unidades por 2.58 €: 0.86 €) Opcional pues podemos cortar y soldar los cables directamente…
  • Jack conector hembra audio 3.5 mm (2 unidades por 1.45 €) Sólo necesario si queremos que el arpa genere sonidos por sí sola, sin
  • Altavoz piezoeléctrico: de cualquier juguete o altavoz malo
  • Transistor NPN 2N222 (10 unidades por 1.62 €: 0.16 €) Solo necesario si el láser no viene con su propio driver.
  • 1 LED
  • Módulo lector de tarjeta SD (1.99 €) y una tarjeta SD. Solo necesario si queremos que al arrancar el arpa láser se reproduzca un archovo wav con el sonido de un sable láser encendiéndose.

TOTAL: Configuración mínima: unos 150€, que podría llegar a ser unos 80 € si usamos un láser malucho (no se verían los haces salvo en una habitación con humo). También depende de los elementos que ya tengamos reciclados de otros inventos.

El láser

Probé con varios láseres, desde los baratos tipo puntero hasta uno «bueno» de 300 mW. Ojo con estos láseres que generalmente vienen de China. Venden diferentes modelos de diferentes potencias, pero luego descubres que te llega exactamente el mismo y que lo único es juegas con el potenciómetro. Así que en caso de utilizar estos láseres, es mejor comprar el de menor potencia y luego ajustar el potenciómetro. Yo alguna vez he jugado con este de 50 mW (11€), y este de 5 mW (5€), y me llegaron exactamente iguales.

El que finalmente utilicé fue este de 300 mW, por unos 80 €. Un láser bueno «de discoteca» puede costar varios cientos de euros o incluso miles. Lo importante es que sea TTL y que tenga cuanta más potencia os podáis permitir, pues entonces podrá verse el haz de láser mejor, o con mayor luz ambiente. Los más típicos (y baratos) son los láseres verdes de 532 nm de longitud de onda.

img_1736

No penséis en ningún momento que puede verse el haz del láser a plena luz del día o, o en una sala muy iluminada. Es necesario que esté en un entorno oscuro, y lo ideal es emplear humo para que se vea mejor…

cuation-laser

Advertencia. Jugar con láseres es muy peligroso, y no es una advertencia banal. En menos tiempo de lo que el ojo puede reaccionar un láser dirigido al ojo, o reflejado en una superficie brillante puede dañar permanentemente tu visión. Para toda la vida. Por ello, es necesario llevar siempre unas gafas protectoras adecuadas al láser específico que estemos manejando. En mi caso empleo láseres de 532 nm, pero ojo, algunos láseres chinos de mala calidad emiten a la vez a 1064 nm, por lo que opté por protegerme para ambas frecuencias y compré estas gafas por unos 35 €.

img_1737

Estas son las características que da el fabricante del láser:

  • Output Wavelength:532nm
  • Output Power:300mW with 5%
  • operating Voltage:DC12V
  • Lifepan:>5000 hours
  • Laser Shape: DOT
  • Focusable:Yes (By Tool)
  • Working Temperature:+10dgC-+40dgC
  • Working Temperature:+10dgC-+50dgC
  • Focus lens:Glass
  • Cooling mode:Heatsink and Fan
  • TTL signal:0~30K

El motor

Aquí está el quid de la cuestión. El láser es importante, sí, pero sólo depende de cuánto me quiera gastar en comprar un láser de mayor potencia, así que hay pocas incógnitas. En cambio con el motor es bastante más delicado. Debe ser muy rápido, y además permitir un control preciso del ángulo de giro para que se dé el efecto de persistencia de la visión y que al reflejar el láser de forma sincronizada con los giros sobre un espejo en el eje del motor dé la sensación de tener varios haces de luz.

Hice muchísimas pruebas con diversos motores y drivers (ver esta entrada). Lo primero, que se pregunta mucho en otras páginas, es dejar claro que el típico stepper de todos los kits de iniciación a la electrónica, el 28BYJ-48 no vale para un arpa láser, es muy lento. Hablo sobre este motor aquí.

En varias páginas se dice que con un motor sacado de una vieja impresora funciona. Yo probé con un MITSUMI M35SP-9, sacado de una vieja impresora Deskjet HP. Puede valer, aunque obtuve mejores resultados con otros motores.

Lo ideal sería emplear un galvanómetro (lo que se emplea en láseres de discoteca) que son capaces de girar a más de 20.000 revoluciones por minuto, pero son extremadamente caros, así que lo descarté desde el principio.

El motor que finalmente empleé fue este de Adafruit, aunque estuve a punto de utilizar uno que rescaté de una vieja impresora.

adafruit

También es muy importante qué driver (controlador) del motor empleamos. En mi caso empleé el A3967 EasyDriver. Aquí se explica de forma muy sencilla su manejo.

En esta entrada explico cómo hacer funcionar el motor con este driver.

MIDI

El protocolo MIDI es bastante sencillo. En esencia, Arduino no genera música, sino que envía comandos por este protocolo para que otra máquina genere la música con el instrumento que queramos. En mi caso, como ya tenía un teclado MIDI (Casio CT-655), solo he tenido que comprar el enchufe MIDI y un cable. También se puede hacer sin un teclado/sintetizador, conectando el cable MIDI al ordenador por un adaptador USB, y configurar el ordenador para que se encargue de generar el sonido que queramos (ver más abajo).

Lo primero es hacer una pequeña prueba para ver que hemos conectado bien todo y que nuestro teclado/sintetizador/ordenador es generar de interpretar lo que Arduino le manda por MIDI y produce sonidos. Podemos seguir el tutorial sencillo que viene en el SDK y la página web de Arduino.

midi_bb

 

En la siguiente página se explica en profundidad el protocolo MIDI y la estructura de comandos. Voy a conectar el arpa láser a un teclado CASIO CT-655, y me interesa, además de las notas en concreto, poder decirle al teclado que cambie a un instrumento determinado.

Por cierto, cada vez que actualicemos el código de Arduino y lo subamos a la placa, debemos desconectar el cable MIDI, pues si no el teclado puede recibir instrucciones erróneas y el resultado que obtendremos sonará muy raro…

 

Audio

Como es un poco trabajoso tener que conectar el arpa láser a un teclado MIDI o a un ordenador para producir algún sonido, he probado a que además de enviar el sonido por MIDI produzca sonido digital directamente, a través de un pequeño altavoz piezo, y un jack de 2.5mm al que se puede conectar unos auriculares.

[Explicar más]

Secuencia de audio al inicio

Se me ocurrió que podía añadir un sonido de encendido de espada láser de Star Wars, así que le añadí un módulo lector de tarjeta SD, busqué por internet y descargué un audio con el sonido de espada láser, lo convertí a wav con el Audacity y pasándolo a mono, 16.000 Hz, 32 bits y grabado como «Unsigned 8-bit PCM». Aquí está el audio final:

 

Diagrama fritzing

Código

El código de Arduino empleado en este proyecto es el siguiente:

#include 	// Cargo la librería de motores a pasos
#include        // Cargo la librería SD, para reproducir audio al comienzo por altavoz
#define SDPin 10      // Conecto el CS al pin 10, para reproducir audio al comienzo por altavoz
#include    // Cargo la librería TMRpcm, para reproducir audio al comienzo por altavoz
#include       // Cargo la librería SPI, para reproducir audio al comienzo por altavoz

TMRpcm audio;   // Creo el objeto audio

int pinStep = 7;  	// Pin de Step del EasyDriver
int pinDirec = 8;	// Pin de Direction del EasyDriver
int micropausa = 600;	// microsegundos de pausa entre (micro)paso y (micro)paso (velocidad del motor)

int micropausaInicio = 15000;  //microsegundos de pausa entre (micro)paso y (micro)paso en la secuencia de inicio

int posVert = 465;  // Número de (micro)pasos que deja el espejo para que el láser esté en su sitio al comienzo

int sensor = 155;   // Umbral de sensibilidad del fotorresitor. Cuanto más bajo, más sensible a la luz. En cuarto oscuro funciona bien con 160

int micropausaLaser = 2000;   // Tiempo que se queda encendido el láser (microsengudos). En mi caso, va bien con 2000
int micropausaSensor = 2000; // Pausa tras apagar láser y antes de girar, para dar tiempo al sensor a reaccionar (microsengudos). En mi caso, va bien con 2000

int haces = 6;        // Número de notas / haces de láser
int pasosHaces = 12;  // Número de (micro)pasos entre haz y haz

int pinLaser = 4;   // Pin donde tengo conectado el láser
int pinLed = 6;     // Pin donde tengo conectado el LED de estado
int pinAudio = 9;   // Pin donde está conectado el altavoz piezo. Debe ser el Pin 9 en Arduino Uno y Nano, y 11 en el Mega
int pinBoton = 3;   // Pin donde está conectado el interruptor de fin de carrera del motor

int valBot = 0;   //Estado del botón del motor

int noteStatus[] = {0,0,0,0,0,0};	// Inicializo el estado de las notas (sonando/no sonando). Debe haber el mismo número que número de haces

int notasMIDI[] = {58,62,65,70,72,74};	// Nota asignada a cada haz. Debe haber el mismo número que número de haces



void setup() {

  pinMode(pinLaser, OUTPUT);        // Declaro el pin del laser
  digitalWrite(pinLaser, LOW);   // Apago el laser

  pinMode(pinLed, OUTPUT);  // Declaro el pin del Led de status
  digitalWrite(pinLed, LOW);  // Dejo el Led de estatus apagado

   // Para que suene el sable láser al arrancar
  audio.speakerPin = pinAudio; // Debe ser el Pin 9 en Arduino Uno y Nano, y 11 en el Mega
  Serial.begin(9600); // Para reproducir el audio al comienzo
  pinMode(SDPin, OUTPUT); 

  ajusteMotor();  // Llamo a la función ajusteMotor() para colocar el espejo en su sitio y arrancar la secuencia de incio

  //Arranco MIDI:
  Serial.begin(31250);	// Especifico el canal de comunicación para MIDI  
  Serial.write(192);	// Byte para cambiar de instrumento en canal 0
  Serial.write(15);	// Número de instrumento

  delay(100);

}

// Pongo el motor/espejo en su sitio al comienzo y secuencia de inicio:
void ajusteMotor()
{
int numpasosini;   //número de pasos en la secuencia de inicio (se calcula automáticamente)
int contini=0;  // contador secuencia de inicio (se calcula automáticamente)
  
  pinMode(pinBoton, INPUT); // Declaro el pin del boton como input
  pinMode(pinDirec, OUTPUT);
  pinMode(pinStep, OUTPUT);
  digitalWrite(pinDirec, LOW);
  digitalWrite(pinStep, LOW);

  for (int pos = 0; pos < 4000; pos++)
  {
   valBot = digitalRead(pinBoton);
   if (valBot == LOW)
   {         // si el botón está pulsado:
    //digitalWrite(pinLed, HIGH);   // Enciendo el led
    digitalWrite(pinDirec, HIGH);  // Cambio la dirección
    for (int pos2 = 0; pos2<posVert; pos2++) { digitalWrite(pinStep, LOW); digitalWrite(pinStep, HIGH); delayMicroseconds(micropausa); } digitalWrite(pinLaser, HIGH); // Enciendo el laser // Reproduzco el sonido de sable láser: if (SD.begin(SDPin)) { // Solo ejecuto si la tarjeta está accesible audio.volume(6); // Fijo el volumen (min=0, max=7) audio.play("laser.wav"); } // Secuencia abanico desplegado totalmente, acelerando linealmente: numpasosini=(haces-1)*pasosHaces*17/2; // Calculo el número de pasos en la secuencia de inicio // Compruebo la célcula fotoeléctrica, y mando arrancar la secuencia de inicio cuando se active: while(true) { if ( (analogRead(0) > sensor*2 ) )     // Si el sensor recibe señal
      {
        digitalWrite(pinLed, HIGH);   // Enciendo el led
        digitalWrite(pinDirec, LOW);  // Cambio la dirección
        for (int pos2 = 0; pos2<((haces-1)*pasosHaces/2); pos2++)
        {
           digitalWrite(pinStep, LOW);
           digitalWrite(pinStep, HIGH);
           digitalWrite(pinLaser, HIGH);   // Enciendo el laser
           delayMicroseconds(micropausaInicio-(micropausaInicio-micropausa)/numpasosini*contini++);
           digitalWrite(pinLaser, LOW);   // Apago el laser
        }
        for (int pos3 = 0; pos3<4; pos3++)
        {
          digitalWrite(pinDirec, HIGH);  // Cambio la dirección
          for (int pos2 = 0; pos2<((haces-1)*pasosHaces); pos2++)
          {
             digitalWrite(pinStep, LOW);
             digitalWrite(pinStep, HIGH);
             digitalWrite(pinLaser, HIGH);   // Enciendo el laser
             delayMicroseconds(micropausaInicio-(micropausaInicio-micropausa)/numpasosini*contini++);
             digitalWrite(pinLaser, LOW);   // Apago el laser
          }
          digitalWrite(pinDirec, LOW);  // Cambio la dirección
          for (int pos2 = 0; pos2<((haces-1)*pasosHaces); pos2++)
          {
             digitalWrite(pinStep, LOW);
             digitalWrite(pinStep, HIGH);
             digitalWrite(pinLaser, HIGH);   // Enciendo el laser
             delayMicroseconds(micropausaInicio-(micropausaInicio-micropausa)/numpasosini*contini++);
             digitalWrite(pinLaser, LOW);   // Apago el laser
          }
        }
        break;
      }
    }

   
//    // Si quiero ahorrarme la secuencia de inicio, habría que comentar la sección anterior.
//    // Dejo el espejo en la posición del primer haz:
//    digitalWrite(pinDirec, LOW);  // Cambio la dirección
//    for (int pos2 = 0; pos2<((haces-1)*pasosHaces/2); pos2++)
//    {
//       digitalWrite(pinStep, LOW);
//       digitalWrite(pinStep, HIGH);
//       delayMicroseconds(micropausa);
//    }     


 
    break;
   }
   else
   {        // el botón no está pulsado:
    digitalWrite(pinLed, LOW);  // Mantengo el led apagado

    digitalWrite(pinStep, LOW);
    digitalWrite(pinStep, HIGH);
    delayMicroseconds(micropausa);

   }
  }
}




void loop()
{
  for (int pos = 1; pos < haces; pos++) { // En una dirección digitalWrite(pinDirec, HIGH); // Establezco la dirección del motor digitalWrite(pinLaser, HIGH); // Enciendo el láser delayMicroseconds(micropausaLaser); // Dejo el láser encendido el tiempo micropausaLaser // Compruebo la célcula fotoeléctrica, y mando tocar/parar de tocar la nota correspondiente: if ( (analogRead(0) > sensor ) && ( noteStatus[pos] == 0 ))     // Si el sensor recibe señal, y la nota no está sonando
    {
      noteMIDI(0x90, notasMIDI[pos-1], 0x45); // Que se toque la nota por MIDI
      //tone(pinAudio,notas[pos-1]);  // Que se toque la nota por el piezo/auriculares
      digitalWrite(pinLed, HIGH); // Enciendo el Led de estado
      noteStatus[pos]++;  // Cambio el estado de esa nota a "sonando"
    }
    else if (analogRead(0) < sensor ) // Si el sensor no recibe señal { if (noteStatus[pos] >= 1) // Si hay una nota tocando (porque aún no la he apagado, aunque no haya señal)
      {
        //if (noteStatus[pos]++ == 2)   //Solo para de sonar si ya han pasado tres ciclos sin recibir señal...
        //{
          noteMIDI(0x90, notasMIDI[pos-1], 0x00);  // Parar de tocar la nota por MIDI
          //noTone(pinAudio);   // Parar de tocar la nota por el piezo/auriculares
          digitalWrite(pinLed, LOW);  // Apago el led de estado
          noteStatus[pos]=0;  // Cambio el estado de esa nota a "apagada"
        //}
      }
    }
    
    digitalWrite(pinLaser, LOW);      // Apago el láser   
    delayMicroseconds(micropausaSensor); // Antes de pasar al siguiente haz, pequeña pausa para reacción del sensor fotoeléctrico

    //Muevo el motor al siguiente haz:
    for (int pos2 = 0; pos2<pasosHaces; pos2++) // Avanzo un haz (el número de (micro)pasos definidos en la variable pasosHaces { digitalWrite(pinStep, LOW); digitalWrite(pinStep, HIGH); delayMicroseconds(micropausa); } } for (int pos = haces; pos > 1; pos--)
  { // En la otra dirección
    digitalWrite(pinDirec, LOW);	// Pongo el motor en el sentido contrario
    digitalWrite(pinLaser, HIGH);	// Enciendo el láser
    delayMicroseconds(micropausaLaser);	// Dejo el láser encendido el tiempo micropausaLaser
    
    // Compruebo la célcula fotoeléctrica, y mando tocar/parar de tocar la nota correspondiente:
    if ( (analogRead(0) > sensor ) && ( noteStatus[pos] == 0 ))     // Si el sensor recibe señal, y la nota no está sonando
    {
      noteMIDI(0x90, notasMIDI[pos-1], 0x45); // Que se toque la nota
      //tone(pinAudio,notas[pos-1]);  // Que se toque la nota por el piezo/auriculares
      digitalWrite(pinLed, HIGH); // Enciendo el Led de estado
      noteStatus[pos]++;  // Cambio el estado de esa nota a "sonando"
    }
    else if (analogRead(0) < sensor ) // Si el sensor no recibe señal { if (noteStatus[pos] >= 1) // Si hay una nota tocando (porque aún no la he apagado, aunque no haya señal)
      {
        //if (noteStatus[pos]++ == 2)   //Solo para de sonar si ya han pasado dos ciclos sin recibir señal...
        //{
          noteMIDI(0x90, notasMIDI[pos-1], 0x00);  // Parar de tocar la nota por MIDI
          //noTone(pinAudio);   // Parar de tocar la nota por el piezo/auriculares
          digitalWrite(pinLed, LOW);  // Apago el led de estado
          noteStatus[pos]=0;  // Cambio el estado de esa nota a "apagada"
        //}
      }
    }
    
    digitalWrite(pinLaser, LOW);      // Apago el láser   
    delayMicroseconds(micropausaSensor); // Antes de pasar al siguiente haz, pequeña pausa para reacción del sensor fotoeléctrico

    //Muevo el motor al siguiente haz:
    for (int pos2 = 0; pos2<pasosHaces; pos2++) // Avanzo un haz (el número de (micro)pasos definidos en la variable pasosHaces
    {
       digitalWrite(pinStep, LOW);
       digitalWrite(pinStep, HIGH);
       delayMicroseconds(micropausa);
    } 
  }
}



void noteMIDI(int cmd, int pitch, int velocity) {
  Serial.write(cmd);
  Serial.write(pitch);
  Serial.write(velocity);
}


Puede descargarse aquí.

 

Pruebas iniciales y montaje

img_1751

 

Detalles

img_2417

img_2418

img_2419

img_2420

img_2421img_2422

img_2423

img_2424

Referencias

http://www.instructables.com/id/Frameless-Laser-Harp/

http://www.instructables.com/id/Easy-and-cheap-Laser-Harp/

http://open-source-energy.org/?topic=1129.0

http://hacknmod.com/hack/create-techno-with-a-laser-harp/

https://gist.github.com/mlorenz92/9775363

http://thecreatorsproject.vice.com/blog/make-peaches-laser-harp-how-to

http://harplaser.blogspot.com.es/

http://laserharpseniorproject.blogspot.com.es/2015/05/tutorial-parts-and-setup.html

Motores paso a paso (stepper motor) con Arduino y varios controladores

Para un proyecto que tengo entre manos, construir un arpa láser, quiero explorar el funcionamiento de los motores paso a paso (steppers) con Arduino. Tengo varios motores y también varios controladores, por lo que haré diversas pruebas con todos ellos.

Esta entrada es más bien una recopilación de datos, enlaces y apuntes míos, pocas explicaciones por el momento, me temo.

Busco conseguir la máxima velocidad del motor, sin requerir un gran par, simplemente para mover un espejo que está pegado a su eje y que he de poder girar a diversas posiciones muy rápido. Al apuntar un láser al espejo, y encenderlo y apagarlo de forma sincronizada con los cambios de posición del motor, quiero conseguir la ilusión de tener varios haces de laser, por persistencia de la visión.

Para hacer funcionar un stepper no basta con enchufarles una corriente continua y listo. Constan de una serie de bobinas que hay que ir accionando consecutivamente para conseguir el movimiento del motor, paso a paso. Además, accionando a la vez varias de las bobinas en secuencias determinadas podemos conseguir micropasos. Para realizar esto empleamos controladores (drivers) que se encargan de todo el proceso.

Motores

Tengo los siguientes motores:

28BYJ-48

Motor paso a paso (stepper) 28BYJ-48

Ya he escrito sobre el uso de este motorcito en esta entrada. Es el motor que viene en todos los kits de Arduino. Se suele controlar con el ULN2003. Compré uno junto con su controlador aquí, por poco más de 2€.

GZGW09

gzgw09

Comprado aquí.

Características:

  • Step angle: 1.8 degree
  • Rated voltage: DC 4.83V
  • Rated current: 0.84A
  • Phase impedance: 5.75 Ohm + / – 10 degree centigrade
  • Phase inductance: 9.3 mH + / – 20 degree centigrade (1kHz 1V RMA)
  • Holding torque: 0.48Nm Min
  • Shaft diameter: 5mm / 0.188 (3/16)
  • Shaft length: 20mm
  • Motor height: 34mm
  • Number of lead wire: 4 wires
  • Driven X-axis and Y-axis movement, sprinkler wire wheel to scroll
  • Great for DIY project
  • Dimensions: 5.8 cm x 4.2 cm x 4.2 cm
  • Weight: 220 g

Motor NEMA 17 JK42HS40-1704 13A

Comprado aquí por 12.50 €.

Características:

  • Número de parte: JK42HS40-1704 13A
  • Tamaño de marco: NEMA17
  • Ángulo del paso: 1,8 grados
  • Voltaje: 3.4V
  • Corriente: 1,7 A/phase
  • Resistencia: 2,0 ohmios/fase
  • Inductancia: 3,0 mH/phase
  • Llevar a cabo el esfuerzo de torsión: 4000g-cm 58.30 OZ-IN
  • Inercia del rotor: 54 g-cm2
  • Esfuerzo de torsión de la muesca: 0,22 kilogramo-cm
  • Número de ventajas de alambre: 4
  • Peso: 0,24 kilogramos
  • Longitud: 40m m
  • Eje del motor: 5mm
  • Longitud del árbol delantero: 20 mm
  • Certificación: CE, ROHS, ISO9001

MITSUMI M35SP-9

Lo saqué de una vieja impresora. Venía con etiqueta, así que puede investigar el modelo y características, ahorrándome mucho trabajo. Es un MITSUMI M35SP-9, y por lo visto es (era) muy típico en impresoras, escáneres, faxes, etc. Es un motor paso a paso (stepper) unipolar.

La ficha puede consultarse aquí, de donde he sacado las siguientes tablas y figuras:

mitusmicuadro

mitsumigrafico

Y aquí hay un vídeo italiano empleando el motor con Arduino UNO y un controlador ULN2003A:

https://youtu.be/oLaTRkZNtNE

Motor de Adafruit

El motor que finalmente empleé fue este de Adafruit, comprado aquí.

adafruit

Drivers

Y tengo los siguientes controladores:

ULN2003

Muy simplón.

L2930

A4988

 

En esta entrada explico cómo usar un motor con este controlador.

DRV8825

Es una versión mejorada del driver A4988.

0j42241200

Características principales:

  • Para motores bipolares
  • Permite microstepping de hasta 1/32
  • 1.5  por fase o 2.2A si se dispone de ventilación forzada de aire o disipadores
  • Interfaz casi idéntica al A4988
  • 45 V máximo
  • Control de corriente máxima con un potenciómetro

Puede consultarse sus características e información adicional en la página de Pololu.

0j4232-1200

En esta entrada explico cómo utilizarlo con Arduino, y en esa otra con una Raspberry Pi.

Esta página compara y explica en mucho detalle los drivers DRV8825 y el A4988, muy recomendable.

Para controlar los motores con este driver, se puede emplear la librería StepperDriver.

http://www.hobbytronics.co.uk/drv8825-stepper-motor-driver

Uno de los motores que voy a emplear con este driver tiene una corriente de 1.7 A por fase, por lo que le colocaré un disipador al driver.

Ajustar la corriente:

A3967 Easydriver

El que yo compré es la versión v4.4 (aunque hay una versión más reciente, la 4.5). Sirve para controlar motores bipolares, y permite micropasos hasta 1/16.

Se puede consultar las especificaciones técnicas del chip A3967 aquí, y del propio modulo EasyDriver aquí.

Lo compré aquí, por poco más de 4€.

  • The EasyDriver is a simple to use stepper motor driver,
    compatible with anything that can output a digital 0 to 5V pulse (or 0 to 3.3V pulse if you solder SJ2 closed on the EasyDriver)
  • EasyDriver requires a 7V to 30V supply to power the motor and can power any voltage of stepper motor.
  • The EasyDriver has an on board voltage regulator for the digital interface that can be set to 5V or 3.3V.
  • Connect a 4-wire stepper motor and a micro controller and got precision motor control!
  • EasyDriver drives bi-polar motors, and motors wired as bi-polar. I.e. 4,6, or 8 wire stepper motors.
  • MS1 and MS2 pins broken out to change micro stepping resolution to full, half, quarter and eighth steps (defaults to eighth)
  • Compatible with 4, 6, and 8 wire stepper motors of any voltage
  • Adjustable current control from 150mA/phase to 750mA/phase
  • Power supply range from 7V to 30V. The higher the voltage, the higher the torque at high speeds
  • Board size: 47 x 20mm
  • Pin header size: 51 x11mm
  • Net weight: 7g

Ejemplos de uso:

Arduino Tutorial: Stepper Motor with EasyDriver

https://www.sparkfun.com/tutorials/400

 

Con el motor GZGW09, la conexión al EasyDriver es:

  • A1: rojo (morado)
  • A2: gris (gris)
  • B1: amarillo (blanco)
  • B2: verde (negro)

Con el motor de Adafruit 200 pasos 12 V 350mA, la conexión al EasyDriver es:

  • A1: rojo
  • A2: amarillo
  • B1: verde
  • B2: gris

Motor JK42HS40-1704, la conexión al EasyDriver es:

  • A1: azul (azul)
  • A2: rojo (morado)
  • B1: verde (verde)
  • B2: negro (gris)

 

Referencias

Stepper Motor on Wikipedia

About Steppers on Adafruit Learn

Stepper motor page on RepRap wiki

http://www.orientalmotor.com/technology/articles/stepper-motor-basics.html

https://www.sparkfun.com/tutorials/400

http://bildr.org/2011/06/easydriver/

http://www.instructables.com/id/Stepper-Motor-Easy-Driver/?ALLSTEPS

http://www.instructables.com/id/Drive-a-Stepper-Motor-with-an-Arduino-and-a-A4988-/

 

Motor paso a paso Adafruit 200 pasos 12 V 350mA con EasyDriver

Voy a utilizar un motor Adafruit de 200 pasos, 12V y 35mA por fase con un controlador EasyDriver y Arduino.

El motor lo compré aquí, por unos 20€. Sus especificaciones pueden consultarse aquí, y sus características principales son:

  • 200 pasos por vuelta, 1.8º
  • Bobina nº 1: cables rojo y amarillo. Bobina nº 2: cables verde y gris.
  • Bipolar de 4 cables
  • Dimensión NEMA17 (42mm
  • 42mm/1.65″ square body
  • 12V
  • 350mA máx
  • 28 oz*in, 20 N*cm, 2 Kg*cm holding torque per phase
  • 35 ohms per winding

adafruit

El controlador EasyDriver lo compré aquí por menos de 5€. Sus características son:

Para ajustar la corriente del Pololu, podemos hacerlo a ojo, aumentando con un destornillador poco a poco, o mejor, midiendo la corriente y ajustándolo a las especificaciones del motor. El siguiente vídeo explica cómo hacerlo midiendo la corrieng:

 

 

Con este pequeño código en el Arduino, me funciona perfectamente:

int pinStep = 9;
int pinDirec = 8;
int pausa = 1000;

void setup() {
pinMode(pinDirec, OUTPUT);
pinMode(pinStep, OUTPUT);
digitalWrite(pinDirec, LOW);
digitalWrite(pinStep, LOW);
}

void loop() {
digitalWrite(pinStep, HIGH);
delayMicroseconds(pausa/2);
digitalWrite(pinStep, LOW);
delayMicroseconds(pausa/2);
}

Referencias

http://www.schmalzhaus.com/EasyDriver/Examples/EasyDriverExamples.html

https://learn.sparkfun.com/tutorials/easy-driver-hook-up-guide

 

 

Controlar un motor paso a paso (stepper) 28BYJ-48 con Arduino

Voy a jugar con un motor paso a paso (stepper motor) con Arduino.
Para saber lo que es un motor paso a paso y cómo funcionan puedes consultar aquí o aquí.

Para manejar el motor con Arduino emplearemos el controlador ULN2003 (el mío en concreto es ULN2003AN). Es muy frecuente encontrar este controlador como parte de un módulo «didáctico» que viene con unos leds que indican qué bobina está funcionando en cada momento.

Motor paso a paso (stepper) 28BYJ-48

Motor paso a paso (stepper) 28BYJ-48

Motor paso a paso (stepper) 28BYJ-48

Motor paso a paso (stepper) 28BYJ-48

El motor tiene dos «modos» de funcionamiento: de paso completo (full-step mode) y de medio paso (half-step mode).

Controlador ULN2003 (suelto, y como parte de un módulo habitual)

Controlador ULN2003 (suelto, y como parte de un módulo habitual)

 

IMG_1375

Tanto el motor como este controlador suelen venir en casi cualquier kit de aprendizaje de Arduino.

El stepper que yo tengo es un 28BYJ-48. Funciona a 5V DC y es muy barato (en torno a 2€).

El esquema de conexión es el siguiente:

700px-Stepper_schematic

Wiring

Conectado quedaría así:

IMG_1369

 

O si empleamos el módulo sería de la siguiente forma:

IMG_1372

Que podemos ahorrarnos los cables si conectamos el módulo directamente a los pines 8, 9 10 y 11 del Arduino, como se muestra en las dos siguientes figuras:

IMG_1370IMG_1371

 

Lo ideal es alimentar el motor desde una fuente externa y no desde la placa de Arduino, ya que en teoría se necesita más corriente de la que Arduino puede proporcionar.

Código

En el IDE de Arduino vienen varios ejemplos que hacen uso del stepper.

 

 

Referencias

Arduino Stepper Motor Control

Instalar No-IP en la Raspberry Pi

Voy a explicar a continuación cómo instalar y configurar una cuenta de No-IP para tener una dns dinámica que sea capaz de actualizarse periódicamente para poder solventar el problema que supone la IP dinámica que seguramente nos provee nuestro ISP.

Lo primero, hay que registrarse en no-ip y obtener un nombre de dominio.

A continuación

mkdir noiptemp
cd noiptemp
wget http://www.no-ip.com/client/linux/noip-duc-linux.tar.gz
tar -zxvf noip-duc-linux.tar.gz
cd noip-2.1.9-1/
make
sudo make install

 

Al compilarlo a mí me dio un par de errores:

gcc -Wall -g -Dlinux -DPREFIX="/usr/local" noip2.c -o noip2
noip2.c: In function ‘dynamic_update’:
noip2.c:1595:6: warning: variable ‘i’ set but not used [-Wunused-but-set-variable]
  int i, x, is_group, retval, response;
      ^
noip2.c: In function ‘domains’:
noip2.c:1826:13: warning: variable ‘x’ set but not used [-Wunused-but-set-variable]
         int x;
             ^
noip2.c: In function ‘hosts’:
noip2.c:1838:20: warning: variable ‘y’ set but not used [-Wunused-but-set-variable]
         int     x, y, z;
                    ^

 

Pero son de variables definidas que no se usan, así que no pasa nada.

Ojo, que es posible que haya que cambiar el nombre de la carpeta, si la versión que descarguéis es posterior.

El instalador nos pregunta nuestro correo o nombre de usuario de no-ip, lo introducimos. También el nombre del host, y el intervalo de refresco. Por defecto viene 30 minutos; yo lo cambio a 5 minutos. También pregunta si queremos ejectuar algo tras actualizar la IP; en mi caso digo que no.

El instalador guarda el archivo de configuración en /usr/local/etc/no-ip2.conf

Y ya podemos borrar la carpeta temporal donde descargamos y descomprimimos el instalador.

Ahora que está instalado y configurado, tenemos que hacer que se inicie el proceso cada vez que reiniciemos. Para ello creamos un rc script:

sudo nano /etc/init.d/noip2

 

Y copiamos el siguiente contenido:

### BEGIN INIT INFO
# Provides:          noip2
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start daemon at boot time
# Description:       Enable service provided by daemon.
### END INIT INFO

 #! /bin/sh
# /etc/init.d/noip


# If you want a command to always run, put it here


# Carry out specific functions when asked to by the system
case "$1" in
  start)
    echo "Starting noip"
    # run application you want to start
    /usr/local/bin/noip2
    ;;
  stop)
    echo "Stopping noip"
    # kill application you want to stop
    killall noip2
    ;;
  *)
    echo "Usage: /etc/init.d/noip {start|stop}"
    exit 1
    ;;
esac

exit 0

Y por último:

sudo chmod +x /etc/init.d/noip2
sudo update-rc.d noip2 defaults

Ahora debemos hacer que se arranque tras cada reinicio. Para ello agregamos /usr/local/bin/noip2 al fichero /etc/rc.local, antes de la última línea, donde pone exit 0.

Ya está. Reiniciamos y debería funcionar.

Crear un servidor VPN en una Raspberry Pi

Uno de los primeros proyectos que hice con una Raspberry Pi fue crear un servidor VPN para poder acceder a mi red doméstica y navegar tranquilamente desde conexiones públicas. O, para cuando viajo a países como China, en los que el acceso a ciertas páginas está bloqueado, poder navegar tranquilamente.

Tengo una Raspberry Pi 2 permanentemente encendida, con una distribución OpenElec para usar Kodi al ver la televisión. Quería utilizar esta máquina como servidor VPN, pero tras investigar mucho he decidido desistir por los muchos problemas que tiene el emplear una distribución no completa como es OpenElec. Así que mejor lo hago en otra Raspberry exclusiva (una B), con una distribución decente, como es Raspbian.

Hay miles de tutoriales por internet sobre cómo hacer esto. Yo voy a seguir fundamentalmente este en dos partes, que me parece maravilloso (aunque hay varias cosas que han cambiado con las nuevas versiones de OpenVPN y no se puede seguir tal cual):

Building A Raspberry Pi VPN Part One: How And Why To Build A Server
Building A Raspberry Pi VPN Part Two: Creating An Encrypted Client Side

Configuraré mi portátil del trabajo (Windows), mi portátil personal (Mac) y mi iPhone para poder acceder a la VPN.

Pasos previos

Instalo Raspbian, cambio la contraseña, compruebo que puedo acceder a la Raspberry Pi por SSH, desde otro ordenador conectado a la misma red local. Y actualizo todo con sudo apt-get update y sudo apt-get upgrade.

También tengo que asegurarme de que la Raspberry Pi tiene asignada una IP estática dentro de la red local, o bien a mano (ver esta entrada) o en mi router. Hecho (no explico cómo hacerlo por el router porque en cada router se hace de una forma, aunque todos son similares). Supongamos que es la 192.168.1.45.

También seguramente necesite un servidor dns dinámico como no-ip.com, para poder acceder desde cualquier sitio al servidor, que seguramente tenga una IP dinámica. Puedo hacerlo siguiendo las instrucción ques expliqué en esta entrada.

Una cosa más en el router: debo hacer que todo paquete que llegue al puerto 1194 UDP sea dirigido a mi Raspberry Pi. Hecho (tampoco lo explico, si tienes dudas, googlea tu modelo de router).

Instalando OpenVPN

Instalo OpenVPN:

sudo apt-get install openvpn easy-rsa

 

Se me instala la versión 2.3.4.

Voy a generar las claves RSA. Empiezo por darme permiso de supersusuario, para no tener que andar haciendo sudo todo el rato:

sudo -s

 

Vamos a emplear easy-rsa.

Y ahora:

mkdir /etc/openvpn/easy-rsa
cp /usr/share/easy-rsa/* /etc/openvpn/easy-rsa/
cd /etc/openvpn/easy-rsa
nano /etc/openvpn/easy-rsa/vars

 

Busco dentro del fichero /etc/openvpn/easy-rsa/vars la línea que dice export EASY_RSA="`pwd`" y lo cambio por:

export EASY_RSA=”/etc/openvpn/easy-rsa” 

 

Y ahora genero los certificados, ejecutando los siguientes comandos:

source ./vars
./clean-all
./build-ca

 

¡Ojo! Si no es la primera vez que seguimos estos pasos es posible que ya tengamos algunos certificados generados en el directorio /etc/openvpn/easy-rsa. En este caso, NO debemos ejecutar el comando ./clean-all

Al ejecutar ./build-ca saltarán una serie de preguntas (Country name, State or Province Name, Locality Name, Organization Name, Organizational Unit Name, Common Name, Name), que yo prefiero no rellenar y dejo los valores por defecto, pulsando Enter.

Ahora definimos el nombre del servidor, en mi caso raspivpn:

./build-key-server raspivpn

 

Nuevamente, nos pedirá rellenar una serie de nombres, que dejo en sus valores por defecto, fijándome que el Common Name que me ofrece por defecto y apruebo es el que di al servidor, raspivpn. El Challenge Pasword lo dejo en blanco, y cuando me pregunte «Sign the certificate? [y/n]», pues diré que sí (y), naturalmente.

Con esto ya tenemos configurado el servidor. Ahora nos queda generar las claves de los clientes y configurarlos.

Creo un certificado para cada usuario:

./build-key-pass usuario1
./build-key-pass usuario2
./build-key-pass usuario3
./build-key-pass usuario4
./build-key-pass usuario5
...

 

Introduzco la contraseña que quiero tenga cuando dice «Enter PEM pass phrase», y el resto de opciones por defecto.

Y ahora encriptamos las llaves con des3:

openssl rsa -in usuario1.key -des3 -out usuario1.3des.key
openssl rsa -in usuario2.key -des3 -out usuario2.3des.key
openssl rsa -in usuario3.key -des3 -out usuario3.3des.key
openssl rsa -in usuario4.key -des3 -out usuario4.3des.key
openssl rsa -in usuario5.key -des3 -out usuario5.3des.key

 

E introducimos una nueva contraseña (o la misma).

Volvemos al directorio de easy-rsa:

cd /etc/openvpn/easy-rsa/ 

 

Ahora generamos el intercambio de llaves Diffie-Hellman. Esto puede tardar (en mi caso, una hora y cuarto, porque dejé la opción por defecto de encriptación 2048 bit):

./build-dh

 

Y la protección contra un ataque de DoS, generando una llave HMAC estática:

openvpn --genkey --secret keys/ta.key

 

Ya está todo instalado y creado. Falta configurar OpenVPN. Para ello vamos a crear un fichero /etc/openvpn/server.conf con el contenido de este archivo.

nano /etc/openvpn/server.conf

 

Más adelante he descubierto que OpenVPN no arranca tras reiniciar el servidor. Investigando, he llegado a que hay que comentar la primera línea de este fichero: # local 192.168.1.45. Entonces, en mi caso, lo dejo así:

#local 192.168.1.45 # SWAP THIS NUMBER WITH YOUR RASPBERRY PI IP ADDRESS
dev tun
proto udp #Some people prefer to use tcp. Don't change it if you don't know.
port 1194
ca /etc/openvpn/easy-rsa/keys/ca.crt
cert /etc/openvpn/easy-rsa/keys/raspivpn.crt # SWAP WITH YOUR CRT NAME
key /etc/openvpn/easy-rsa/keys/raspivpn.key # SWAP WITH YOUR KEY NAME
dh /etc/openvpn/easy-rsa/keys/dh2048.pem # If you changed to 2048, change that here!
server 10.8.0.0 255.255.255.0
# server and remote endpoints
ifconfig 10.8.0.1 10.8.0.2
# Add route to Client routing table for the OpenVPN Server
push "route 10.8.0.1 255.255.255.255"
# Add route to Client routing table for the OpenVPN Subnet
push "route 10.8.0.0 255.255.255.0"
# your local subnet
push "route 192.168.1.45 255.255.255.0" # SWAP THE IP NUMBER WITH YOUR RASPBERRY PI IP ADDRESS
# Set primary domain name server address to the SOHO Router
# If your router does not do DNS, you can use Google DNS 8.8.8.8
push "dhcp-option DNS 192.168.1.1" # This should already match your router address and not need to be changed.
# Override the Client default gateway by using 0.0.0.0/1 and
# 128.0.0.0/1 rather than 0.0.0.0/0. This has the benefit of
# overriding but not wiping out the original default gateway.
push "redirect-gateway def1"
client-to-client
duplicate-cn
keepalive 10 120
tls-auth /etc/openvpn/easy-rsa/keys/ta.key 0
cipher AES-128-CBC
comp-lzo
user nobody
group nogroup
persist-key
persist-tun
status /var/log/openvpn-status.log 20
log /var/log/openvpn.log
verb 1

 

Otra cosa, tenemos que redirigir el tráfico de internet, ya que Raspbian por defecto no lo hace. Para ello editamos el siguiente fichero:

nano /etc/sysctl.conf

 

Buscamos la línea donde dice:

# Uncomment the next line to enable packet forwarding for IPv4
#net.ipv4.ip_forward=1

 

Y lo descomentamos:

# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1

 

Aplicamos los cambios con el siguiente comando:

sysctl -p

 

Ahora queda desbloquear OpenVPN en el firewall, y además hacer que se haga en cada reinicio, ya que las excepciones del cortafuegos no se quedan grabadas. Para ello creamos este pequeño script:

nano /etc/firewall-openvpn-rules.sh

 

Y dentro del fichero escribimos lo siguiente:

#!/bin/sh
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j SNAT --to-source 192.168.1.45

 

Grabamos y salimos. Ahora toca darle permisos de ejecución a este fichero, y cambiarle el usuario a root:

chmod 700 /etc/firewall-openvpn-rules.sh 
chown root /etc/firewall-openvpn-rules.sh

 

En las versiones anteriores de Raspbian, bastaba con editar el fichero /etc/network/interfaces:

nano /etc/network/interfaces

 

buscar la línea:

iface eth0 inet manual

 

y debajo de ella, con un sangrado, añadir:

    pre-up /etc/firewall-openvpn-rules.sh

 

Pero si se tiene Raspbian Jessie o superior, hay que añadir además «auto eth0» en la línea anterior, de forma que finalmente debe quedar así:

auto eth0
iface eth0 inet manual
   pre-up /etc/firewall-openvpn-rules.sh

 

Con esto ya garantizamos que tras cada reinicio se abre el Firewall para OpenVPN. Así que reiniciamos la Raspberry Pi:

reboot

 

Configurando el cliente

Ya tenemos el servidor VPN en marcha. Ahora vamos a configurar los clientes.

Pero seguimos todavía en el servidor. Vamos a crear los ficheros de configuración que instalaremos en los clientes.

Creamos un fichero:

nano /etc/openvpn/easy-rsa/keys/Default.txt

Y copiamos lo siguiente:

client
dev tun
proto udp
remote TU-SERVIDOR-AQUI 1194
resolv-retry infinite
nobind
persist-key
persist-tun
mute-replay-warnings
ns-cert-type server
key-direction 1
cipher AES-128-CBC
comp-lzo
verb 1
mute 20 

Donde dice TU-SERVIDOR-AQUI pondremos la dirección pública de nuestro servidor. Puede ser una IP, o un nombre como mi.servidorVPN.com. Lo más probable es que aquí pongas una dirección de dominio dinámico gratuita como las que ofrece no-ip.com, que expliqué cómo se hace en otro post.

Ahora para generar los ficheros de configuración de cada cliente descargamos este pequeño script maravilloso aquí, y copiamos su contenido en un fichero en /etc/openvpn/easy-rsa/keys/MakeOVPN.sh (he corregido dos cosas menores):

#!/bin/bash 
 
# Default Variable Declarations 
DEFAULT="Default.txt" 
FILEEXT=".ovpn" 
CRT=".crt" 
KEY=".3des.key" 
CA="ca.crt" 
TA="ta.key" 
 
#Ask for a Client name 
echo "Please enter an existing Client Name:"
read NAME 
 
 
#1st Verify that client’s Public Key Exists 
if [ ! -f $NAME$CRT ]; then 
 echo "[ERROR]: Client Public Key Certificate not found: $NAME$CRT" 
 exit 
fi 
echo "Client’s cert found: $NAME$CR" 
 
 
#Then, verify that there is a private key for that client 
if [ ! -f $NAME$KEY ]; then 
 echo "[ERROR]: Client 3des Private Key not found: $NAME$KEY" 
 exit 
fi 
echo "Client’s Private Key found: $NAME$KEY"

#Confirm the CA public key exists 
if [ ! -f $CA ]; then 
 echo "[ERROR]: CA Public Key not found: $CA" 
 exit 
fi 
echo "CA public Key found: $CA" 

#Confirm the tls-auth ta key file exists 
if [ ! -f $TA ]; then 
 echo "[ERROR]: tls-auth Key not found: $TA" 
 exit 
fi 
echo "tls-auth Private Key found: $TA" 
 
#Ready to make a new .opvn file - Start by populating with the default file 
cat $DEFAULT > $NAME$FILEEXT 
 
#Now, append the CA Public Cert 
echo "" >> $NAME$FILEEXT 
cat $CA >> $NAME$FILEEXT 
echo "" >> $NAME$FILEEXT

#Next append the client Public Cert 
echo "" >> $NAME$FILEEXT 
cat $NAME$CRT | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' >> $NAME$FILEEXT 
echo "" >> $NAME$FILEEXT 
 
#Then, append the client Private Key 
echo "" >> $NAME$FILEEXT 
cat $NAME$KEY >> $NAME$FILEEXT 
echo "" >> $NAME$FILEEXT 
 
#Finally, append the TA Private Key 
echo "" >> $NAME$FILEEXT 
cat $TA >> $NAME$FILEEXT 
echo "" >> $NAME$FILEEXT 
 
echo "Done! $NAME$FILEEXT Successfully Created."

#Script written by Eric Jodoin
#No newline at end of file

 

Damos permiso de ejecución al script:

cd /etc/openvpn/easy-rsa/keys/
chmod 700 MakeOVPN.sh

 

Y ejecutamos el script:

./MakeOVPN.sh

 

Nos pide el nombre del cliente. Introduzco usuario1, trabaja un poco y crea el fichero usuario1.ovpn. Repito con el resto de usuarios.

De esta forma se me generan unos ficheros usuario1.ovpn, usuario2.ovpn, etc. que son los que cargaré a continuación en los clientes.

Basta con cargar el fichero .ovpn, introducir la contraseña, y listo.

Lo he probado de forma exitosa en:

iPhone, con OpenVPN.
Mac, con TunnelBlick
Windows, con OpenVPN Connect

Me consta que OpenVPN Connect también funciona en Android, pero no lo he probado.

Referencias

https://nxfifteen.me.uk/2015/02/07/raspberry-pi-powered-openvpn-server/

IP estática en la Raspberry Pi

Hay varias formas de asignar una IP estática a nuestra Raspberry Pi. Una de ellas es entrar en la configuración del router, averiguar la dirección MAC de la tarjeta de red o wifi de la Raspberry Pi, y asignarle desde ahí una IP estática. Otra forma es configurando la propia Raspberry para que tenga la IP estática, que es como voy a explicar aquí.

Lo primero que tenemos que hacer es conectar nuestra Raspberry Pi por cable a la red. Si el router o servidor tiene un servicio DHCP, habrá asignado automáticamente una dirección IP a nuestra máquina. A continuación, ejecutamos el comando ifconfig y obtenemos información de la red, que vamos a necesitar para configurar adecuadamente la IP estática:

ifconfig

Obtenemos la siguiente pantalla:
Captura

Me fijo en inet addr:192.168.1.45, Bcast:192.168.1.255 y Mask:255.255.255.0

Ejecuto ahora el comando netstat -nr:

netstat -nr

Y obtengo:
Captura

Me fijo en: Gateway 192.168.1.1 y Destination 192.168.1.0

Con estos datos ya podría editar el fichero /etc/network/interfaces e introducir ahí la configuración de la IP estática. ¡Pero desde la versión 20150505 de Raspbian (Jessie) ya no se hace así! Ahora hay un demonio llamado dhcpcd, que cambia un poco cómo sea hace.

Lo más fácil es editar el fichero /etc/dhcpcd.conf y añadir al final:

# IP estática en eth0:
interface eth0
static ip_address=192.168.1.45/24
static routers=192.168.1.1
static domain_name_servers=192.168.1.1

El /24 tras la dirección IP indica que la netmask es 255.255.255.0, como obtuvimos arriba.

sudo nano /etc/network/interfaces

Ya está. Reiniciamos y listo.

Referencias
ModMyPi
Sizious.com

Display Adafruit 0.56» de 4 dígitos de 7 segmentos I2C en la Raspberry Pi

En este post expliqué cómo hacer funcionar un display de 4 dígitos de 7 segmentos con la Raspberry Pi. Ahora voy a explicar como hacerlo de forma más sencilla, empleando el display de Adafruit, que lleva un controlador incorporado y podemos controlarlo por medio de I2C empleando sólo cuatro cables. Está todo muy bien explicado en la página de Adafruit, así que sigo tal cual los pasos allí indicados.

Lo primero que tenemos que hacer es configurar la Raspberry Pi para I2C.
Luego ejecuto sudo raspi-config y activo I2C, indicando que se cargue en el arranque:
8- Advanced Options
A7 I2C Enable/Disable automatic loading of I2C Kernel module
Would you like the ARM I2C interface to be enabled?
Would you like the I2C kernel module to be loaded by default?

Edito el fichero sudo nano /etc/modules y añado estas dos líneas al final:

i2c-bcm2708 
i2c-dev

Edito el fichero sudo nano /boot/config.txt y añado al final:

dtparam=i2c1=on
dtparam=i2c_arm=on

Reinicio.

Ahora instalo lo siguiente:

sudo apt-get install python-smbus i2c-tools

Ahora conecto el display, de la siguiente forma:

Display VCC —-> RPi 5V (por ejemplo, pin 5)
Display GND —-> RPi GND (por ejemplo, pin6)
Display SDA —-> RPi SDA (pin 3)
Display SCL —-> RPi SCL (pin 5)

Compruebo a ver si funciona, ejecutando:

sudo i2cdetect -y 1

Me sale:

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: 70 -- -- -- -- -- -- --   

El 70 está indicando que tengo algo conectado ahí, así que por el momento, todo bien.

Ahora me voy a instalar las librerías de Adafruit:

sudo apt-get install git
git clone https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code.git
cd Adafruit-Raspberry-Pi-Python-Code
cd Adafruit_LEDBackpack 

Y pruebo el ejemplo del reloj:

sudo python ex_7segment_clock.py

¡Funciona!

Referencias