Mejora DMA en Prototipo de Driver Dynamixel con Teensy 3.2

Después de hacer un poco de investigación. decidí configurar mi Prototipo de Driver Dynamixel  con Teensy 3.2 para mi DARwIn-OP de forma de eliminar el código de retransmisión del loop:

void loop() 
{
  if (Serial1.available())
  {
    uint8_t c = Serial1.read();
    Serial1.write(c);
  }
}

Este loop simplemente espera por un byte recibido por la UART y lo retransmite en la misma UART, la cual está configurada con un pin de dirección por hardware (RTS manejado por el transmisor).

Si pudiera usar el controlador DMA (Direct Memory Access) del Teensy para hacer la retransmisión, podría vaciar el código loop y  utilizar el Teensy para otras tareas sin afectar el rendimiento de la retransmisión.

Los requerimientos para el DMA son bien simples:

  • Gatillar un requerimiento DMA cuando 1 byte es recibido por la UART.
  • La transferencia DMA tiene que ser de 1 byte.
  • La transferencia DMA debe leer desde el registro de DATA de la UART (data recibida).
  • La transferencia DMA debe escribir en el registro de DATA de la UART (para retransmisión).
  • No se tiene que involucrar la CPU en el proceso, no debe necesitarse eventos de interrupción o pooling.

Mirando a las capacidades del DMA de la CPU ARM MK20DX256VLH7 del Teensy, se ve factible, quedando operativo después de algunas pruebas.

Ahora la retransmisión tiene una latencia menor y un timing más parejo:

Teensy with UART DMA
Teensy con UART manejada por DMA

Las señales en el gráfico son:

  • RX del Teensy (viene del TX del Odroid).
  • TX del Teensy.
  • Pin de Dirección por Hardward.

La codificación ahora tiene un setup más grande para configurar el DMA y la UART (la API serial del Teensy ya no es útil), pero la función loop() ahora está vacía:

#define UART_TXRTSE (2)
#define UART_TXRTSPOL (4)

#define BAUD_RATE (1000000)

void setup() 
{
  int divisor = BAUD2DIV(BAUD_RATE);  

  // DMA:
  
  // p 415 source address = uart data register
  DMA_TCD1_SADDR = &UART0_D;

  // p 415 source address offset
  DMA_TCD1_SOFF = 0;

  // p 416 transfer attributes: 8 bits
  DMA_TCD1_ATTR = 0;

  // p 417 minor byte count = 1 byte
  DMA_TCD1_NBYTES_MLNO = 1;

  // p 420 last source address adjustment = 0
  DMA_TCD1_SLAST = 0;

  // p 420 destination address = uart data register
  DMA_TCD1_DADDR = &UART0_D;

  // p 421 destination address offset
  DMA_TCD1_DOFF = 0;

  // p 423 channel link disabled
  DMA_TCD1_CITER_ELINKNO = 1;

  // p 423 last destination address adjustment = 0
  DMA_TCD1_DLASTSGA = 0;

  // p 427 channel link disabled
  DMA_TCD1_BITER_ELINKNO = 1;
  
  // p 424 control and status = 8 cycle stall, active
  DMA_TCD1_CSR = DMA_TCD_CSR_BWC(3) | DMA_TCD_CSR_ACTIVE;

  // p 402 enable DMA REQ channel 1.
  DMA_SERQ = DMA_SERQ_SERQ(1);

  // clock setup
  // p 252-259 system clock gating
  SIM_SCGC6 |= SIM_SCGC6_DMAMUX;
  SIM_SCGC7 |= SIM_SCGC7_DMA;
  SIM_SCGC4 |= SIM_SCGC4_UART0;
  
  // wait for clocks to become stable.
  delay(500);

  // p366 dma mux channel configuration  
  DMAMUX0_CHCFG1 = DMAMUX_ENABLE | DMAMUX_SOURCE_UART0_RX;

  // UART:
  
  // p 1222 UART0 Control Register 5 request DMA on receiver full
  UART0_C5 = UART_C5_RDMAS;

  // RX TX pins
  CORE_PIN0_CONFIG = PORT_PCR_PE | PORT_PCR_PS |
                     PORT_PCR_PFE | PORT_PCR_MUX(3);

  CORE_PIN1_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE |
                     PORT_PCR_MUX(3);

  // p 1208 uart0 baud rate  
  UART0_BDH = (divisor >> 13) & 0x1F;
  UART0_BDL = (divisor >> 5) & 0xFF;
  UART0_C4 = divisor & 0x1F;

  UART0_C1 = UART_C1_ILT;
  UART0_TWFIFO = 2; // tx watermark
  UART0_RWFIFO = 1; // rx watermark
  UART0_PFIFO = UART_PFIFO_TXFE | UART_PFIFO_RXFE;

  UART0_C2 = UART_C2_TE | UART_C2_RE | UART_C2_RIE;

  // enable PIN 6 as hardware transmitter RTS with active HIGH.
  CORE_PIN6_CONFIG = PORT_PCR_MUX(3);
  UART0_MODEM = UART_TXRTSE | UART_TXRTSPOL; 
}

void loop() 
{
}

En realidad, por ahora ejecuto el típico ‘blink’ en la funcion loop() para saber que el Teensy está corriendo.

Fresado CNC mejorado

Continuando con mi clon de robot DARwIn-OP, estoy cortando las piezas de los hombros.

Después de cortar la mayoría de las piezas del robot, estoy llegando a un mejor setup para cortes en mi fresadora CNC Sherline.

Primero empecé sujetando las planchas de aluminio sobre pequeñas placas de madera MDF, cortando con fresas de 3mm, una broca centro y varias brocas (1,6mm, 2,0mm, 2,05mm, 2,5mm y 2,6mm), después pasé a usar una fresa de 2.5mm para mejor acabado en los rebajes. Siguiendo el Manual de Fabricación de DARwIn-OP puse puntos de unión en los cortes finales de las piezas para que no se suelten. Después reemplacé el uso de una placa MDF de base por una de aluminio. Después probé fresar todo con sólo una fresa de 1.5mm, pero no me gustó el acabado y la calidad de los hoyos.

Ahora creo que tengo un mejor setup:

      • Siguiendo el setup de un amigo, reemplacé mi placa matriz de aluminio con una placa de MDF del mismo tamaño y sujeción.
      • Sujeto las planchas de aluminio con varios tornillos de 2.5mm x 10mm al rededor de la pieza a cortar. Para eso hago hoyos de 2mm x 9mm al MDF. Después de varios cortes, la placa de MDF puede ser reemplazada por otra.
      • Volví a usar una fresa de 2.5mm (o 2mm según la parte a cortar, aunque el manual de fabricación recomienda una fresa de 3mm, algunos diseños requieren cortes de radio 1mm).
      • Volví a usar brocas de 1,6mm, 2,0mm, 2,05mm, 2,5mm y 2,6mm. Pero como uso ‘fresa brocas’ de carburo, ya no estoy usando la broca centro para marcar las perforaciones. (Después de varias pruebas no noté corrimiento en los hoyos).

        Drill
        Broca
      • Ya no estoy dejando puntos de unión en los cortes finales. Ahora atornillo la pieza al MDF antes del corte final usando varios de los hoyos originales de la pieza.
      • Para espacios grandes que deban ser vaciados dentro de una pieza, freso completamente el espacio para que no se desprendan pedazos de aluminio que puedan romper la fresa. Si el espacio es muy grande, entonces también lo atornillo para fresar menos.
      • También reemplacé el cabezal de mi fresadora Sherline con un modelo ER-16 (también de Sherline). Esto permite cambios de herramientas más fáciles y hay pinzas de sujeción (o collets) disponibles como las Techniks con muy buena precisión lo que es importante para mantener fresas pequeñas bien centradas.
      • Actualicé mi fresadora a 10k RPM (con un set de Sherline).
      • Con la fresa de 2.5mm estoy cortando a 5k RPM, 200mm/s de avance y 0.4 de profundidad de corte. Con la fresa de 2mm cambio la profundidad de corte a 0.25mm.
      • No uso lubricante, solamente un soplador de aire para mantener limpia el área de corte (ver foto).

La siguiente foto muestra el setup durante el último corte final:

Cutting DARwIn-OP shoulders
Cortando los hombros del robot DARwIn-OP

Los  archivos gcode más viejos que escribí no siguen estas reglas, pero no es difícil actualizarlos.

Cuerpo del robot DARwIn-OP

Mi clon de DARwIn-OP ya está tomando forma. Ya monté la sección del abdomen.

DARwIn-OP de los pies a los hombros.
DARwIn-OP de los pies a los hombros.

Las piezas del pecho donde va instalado el computador son bastante grandes y mi fresadora no tenía el rango necesario en el eje Y para fresarla de una sola vez. Por suerte un amigo que conocí vía este blog me ayudó con el corte, él tiene una fresadora Sherline que modificó y automatizó con mucho más rango en el eje Y, además es dealer de Sherline en Chile y trabaja en esto, tiene su propio blog con varios proyectos bien interesantes en metaltronics.wordpress.com.

Fresado en Sherline modificado
Fresado en Sherline modificado.

Para estos cortes, probamos usar sólo una fresa de 1.5mm para todo el fresado, incluyendo perforaciones (1.6mm las más pequeñas). Para futuros cortes voy a utilizar fresas más grandes, de 2mm o 2.5mm como en los cortes anteriores, la fresa de 1.5mm requiere una profundidad de pasada muy baja (usamos 0.2mm) y son más frágiles.

Como no voy a usar la electrónica original del DARwIn-OP (Fit-PC + controlador CM-730), las piezas del pecho las modifiqué para montar un computador Odroid-XU3, en particular para el acceso a puertos traseros y los puntos de fijación.

Partes del pecho con Odroid-XU3 y servos de hombros y cuello.
Partes del pecho con Odroid-XU3 (y USB2AX montado) y servos de hombros y cuello.

El Odroid-XU3 cabe sin problemas, para montar el USB2AX (interfaz a los servos) tuve que ajustar el conector TTL a posición vertical.

En la parte posterior, expuse el puerto Ethernet, 4 puertos USB 2.0 y espacio para un micro-HDMI (vía un extensor de 15cm). Probablemente termine dejando sólo 2 puertos USB expuestos, desoldando un conector para contar con más puertos USB internamente.

Puertos del Odroid-XU3 expuestos
Puertos del Odroid-XU3 expuestos.

La pieza superior del pecho fue modificada para fijar el 10-DOF con el acelerómetro y giroscopio, centrando el chip del acelerómetro en la misma posición en la iría si hubiera usado el controlador original CM-730. Además dejé 2 líneas de perforaciones con hilo de 2.5mm para montar otros componentes de ser necesario.

10DOF montado
10-DOF montado.

Debido al cambio de la electrónica que estoy haciendo, es necesario utilizar un hub TTL Dynamixel de 6 bocas para distribuir la comunicación y energía a los servos, en la parte posterior hay justo espacio para montarlo.

Hub dynamixel de 6 puertos
Hub dynamixel de 6 puertos.

Piezas de Montaje de Piernas de DARwIn-OP

Fresé las piezas PR13_B_SPACER_PELV que son las piezas de montaje que van sobre las piernas.

DARwIn-OP Mounting Brackets
Piezas de Montaje de Piernas

Estas piezas de montaje son necesarias para unir las piernas con la sección del pecho donde va el computador central. Actualmente estoy rediseñando las piezas del pecho para acomodar un computador Odroid-XU3, el cambio principal es en la posición de puertos USB y Ethernet expuestos al exterior.

Los archivos de corte de las piezas de montaje están en SourceForge aquí. En el archivo  README están las lista de archivos gcode necesarios.

Para las futuras partes voy a tratar de cambiar la estrategia de fresado. En vez de usar varias brocas y fresas, voy a tratar de usar solo una fresa de 1.5mm para todos los cortes, y así evitar cambio de herramientas.

Cubiertas de DARwIn-OP

Recién recibí las cubiertas de plástico para mi clon de robot DARwIn-OP. Los imprimí en naranjo en un servicio de impresión 3D SLS.

Los modelos 3D de las cubiertas están publicados en este archivo ZIP en el repositorio original SourceForge de  DARwIn-OP.

Probé el ensamblado de la pierna izquierda y se ve muy bien comparado con la pierna derecha desnuda.

Cubierta de Pierna de DARwIn-OP
Cubierta de Pierna

Segunda Pierna de mi Clon de Robot DARwIn-OP

Terminé de ensamblar la segunda pierna de mi clon de DARwIn-OP.

2 DARwIn-OP legs
2 piernas de DARwIn-OP

También terminé de escribir los archivos de corte gcode para las piezas de montaje pélvico (PR13_B_SPACER_PELV) que van entre las piernas y el pecho, las voy a cortar pronto.

Mientras tanto estaba rediseñando las piezas del pecho para acomodar el computador ARM ODROID-XU en vez del original FitPC con procesador Intel. Como alternativa también voy a permitir instalar un computador ODROID-U3 que es más pequeño y con menos capacidad de cómputo, pero también menos consumo. El último ODROID-U3 (Revisión 0.5) tiene una interfaz nativa SPI que podría servir para conectar sensores como el acelerómetro y giroscopio.

Pero ahora Hardkernel está por liberar el ODROID-XU3 en agosto y algo de información está disponible, las mayores diferencias con el ODROID-XU que encuentro interesantes para mi proyecto son:

  • Cores Cortex-A15 más rápidos (2GHz).
  • Octa-core de verdad con multi procesamiento heterogéneo.
  • Más eficiente.
  • Ya no tiene el conector LCD para obtener el bus I2C #1 nativo, pero ahora éste está disponible en el connector de expansión I/O que es de más fácil uso.
  • Incluye sensores de consumo.
  • Agrega entrada de audio (mono solamente).
  • OpenCL funciona en Linux.
  • Mismo tamaño que el ODROID-XU, así que es fácil de reemplazar.

De todas maneras, estoy viendo cómo cortar las piezas del pecho en mi Fresadora Sherline, que es muy pequeña para estas piezas, así qie las haré en partes.

Probando el I2C del ODROID-XU

Decidí hacer algunas pruebas de electrónica y software antes de terminar de fabricar la segunda pierna de mi clon del robot DARwIn-OP.

Conecté mi ODROID-XU con el módulo 10DOF GY-80 usando el bus I2C del conector LCD y un PCA9306 para ajustar voltages de la comunicación.

Setup de Prueba de I2C con ODROID-XU
Setup de Prueba de I2C con ODROID-XU

El siguiente es el diagrama de interconexión probado:

Diagrama de Prueba I2C
Diagrama de Prueba I2C

Este 10DOF puede energizarse desde 2V hasta 5.5V (VDD). Sus sensores están alimentados internamente a 3.3V, pero según esta documentación su interfáz I2C está ajustada a VDD, por lo que el PCA9306 tiene que traducir entre los 1.8V del ODROID-XU y VDD (y no 3.3V).

Este 10DOF tiene 4 dispositivos I2C con las siguientes direcciones:

  • 0x1E: compás de 3 ejes (chip HMC5883L)
  • 0x69: giroscopio de 3 ejes (chip L3G4200D)
  • 0x53: acelerómetro de 3 ejes (chip ADXL345)
  • 0x77: sensores de presión y temperatura (chip BMP085)

Con este pequeño programa, se puede consultar el chip del acelerómetro para detectarlo y verificar el setup. Actualmente estoy probando Ubuntu Server 14.04 de paquete en el ODROID-XU, el que incluye el compilador GCC por defecto.

Ahora que tengo la comunicación I2C funcionando, seguí la documentación de los chips y ejemplos en Internet para escribir un borrador de clases C++ para leer los sensores del 10DOF. Están disponibles en esta Sección de Código en el repositorio SourceForge para clonar el Robot DARwIn-OP.

Probé en forma exitosa el 10DOF energizándolo (junto al PCA9306) con 3.3V y 5V, pero a 3.3V consumen 0.024A (o 0.079W) y a 5V consumen 0.085A (o 0.425W). Así que en mi diseño final para el DARwIn-OP probablemente incluya un regulador de 3.3W para disminuir el consumo.

Periféricos del clon de DARwIn-OP

El robot original DARwIn-OP usa un computador Intel Atom Z530 de 1.6 GHz y un controlador ARM CM-730. Este controlador incluye un giroscopio de 3 ejes, un acelerómetro de 3 ejes y un bus Dynamixel para conectar los servos del robot.

Por mi parte, pretendo usar una electrónica alternativa basada en un computador ARM más poderoso (y barato). Para el computador principal, mi candidato es el ODROID-XU que es un quad Cortex-A15 1.6GHz con 2GB de RAM.

En vez del controlador, usaré un USB2AX para conectar los servos Dynamixel y varios componentes I2C para el giroscopio y acelerómetro.

odroidxu-peripherals
ODROID-XU y periféricos

En la imagen se muestran los componentes que ya tengo que estaré probando:

  • Conversor ADC I2C de 12 bit y 4 canales (chip ADS1015)
  • Traductor de voltaje I2C (chip PCA9306)
  • un multi componente I2C 10DOF con sensores de giroscopio de 3 ejes, acelerómetro de 3 ejes, compás de 3 ejes, temperaura y presión (chips, L3G4200D, ADXL345, HMC5883L, BMP085)
  • Resistencia sensora de fuerza (.1N to 100N)
  • USB IO Board para ODROID con interfaces de GPIO/PWM/SPI/UART/I2C/ADC
  • Interfaz Dynamixel USB2AX

Usaré el bus I2C nativo I2C_0 que se encuentra en el conector LCD (CON15) en la parte inferior del ODROID-XU (el esquemático está disponible en Hardkernel vía petición por email).

ODROID-XU LCD connector and cable
conector LCD del ODROID-XU y cable

El conector LCD es un IPEX de 40 pines de 0.5mm. Compré un par de cables en Ebay, aunque ahora noté que Hardkernel (el fabricante de ODROID) lo ofrece a la venta también. La configuración de pines que usaré para la interfaz I2C es:

  • 4 – 1.8V
  • 6 – SCL
  • 7 – SDA
  • 10 – GND

La interfaz I2C del ODROID-XU es de 1.8V, por lo que el PCA9306 servirá para interconectar el resto de los componentes I2C que son de mayor voltaje.

El DARwIn-OP requiere un giroscopio y acelerómetro, pero me interesa usar el compás y los sensores de fuerza (vía los conversores AD) para una futura versión de los pies del DARwIn-OP.

Extensión de Eje X de Fresadora Sherline

Decidí agrandar el eje X de mi fresadora Sherline con una tabla de 19″ de A2Z y una placa matriz de High Tech Systems de 14″. Sherline tiene una tabla extendida pero quise probar esta marca porque es un poco más alta y fresar las piezas para el robot DARwIn-OP  es un trabajo de muy bajo perfil y las fresas son cortas. La placa matriz ayuda en altura y permite soportar un trabajo de 4″ de ancho.

Extended Table and Matrix Plate
Tabla Extendida y Placa Matriz

La placa matriz es bastante buena, sólo recibió un golpe en una esquina, probablemente en el envío a Chile. La tabla extendida es muy larga, instalarla requirió adelgazar la pieza de ajuste de la cama lo que me tomó horas. Ahora tengo un eje X de 360mm de rango.

Hice un nuevo patrón de agujeros en la placa matriz para sujetar mejor las planchas de aluminio para cortar las piezas del DARwIn-OP.

New Hole Pattern
Nuevo Patrón de Agujeros

El patrón de agujeros es para hilo M2.5. Están separados en ½” para alinearlo al patrón preexistente. Hice 3 líneas de agujeros uno al medio y una a  5/32″ de cada borde de la placa de 4″.