Tabla de contenido:

A Hearing MeArm, impulsado por el acelerador de TPU de Google Coral: 3 pasos
A Hearing MeArm, impulsado por el acelerador de TPU de Google Coral: 3 pasos

Video: A Hearing MeArm, impulsado por el acelerador de TPU de Google Coral: 3 pasos

Video: A Hearing MeArm, impulsado por el acelerador de TPU de Google Coral: 3 pasos
Video: Robot Arm & Controller - Building the DFRobot 5 DOF Robot Arm 2024, Mes de julio
Anonim
A Hearing MeArm, impulsado por el acelerador de TPU de Google Coral
A Hearing MeArm, impulsado por el acelerador de TPU de Google Coral
A Hearing MeArm, impulsado por el acelerador de TPU de Google Coral
A Hearing MeArm, impulsado por el acelerador de TPU de Google Coral
A Hearing MeArm, impulsado por el acelerador de TPU de Google Coral
A Hearing MeArm, impulsado por el acelerador de TPU de Google Coral
A Hearing MeArm, impulsado por el acelerador de TPU de Google Coral
A Hearing MeArm, impulsado por el acelerador de TPU de Google Coral

A continuación, me gustaría describir una versión controlada por voz del MeArm, un pequeño brazo robot xyz con una pinza. Utilicé el MeArm Pi de las industrias MIME, pero el sistema debería ser aplicable a cualquier versión del MeArm, o dispositivos similares servoaccionados.

El uso del Acelerador de TPU de Google Coral permite ejecutar scripts de reconocimiento de voz TensorFlow sin conexión rápidos en la Raspberry Pi y, por lo tanto, controlar los dispositivos físicos mediante órdenes habladas, con una latencia inferior a un segundo.

El dispositivo descrito en este documento es una combinación y extensión de los conceptos descritos en dos instructivos anteriores. Es una extensión de una implementación anterior del control de voz de Google Coral, un Jumping Jack, que se describe aquí y una gran mejora de un MeArm controlado por voz de Google AIY que se describe aquí.

El MeArm controlado por voz que usaba el sistema AIY de Google Voice requería acceso en línea, no era fácil de implementar, requería presionar un botón para activar la escucha de órdenes de voz y tenía un tiempo de latencia prolongado. El Acelerador de TPU de Google Coral que se usa ahora permite ejecutar modelos de TensorFlowLite sin conexión con una alta velocidad en una Raspberry Pi u otros dispositivos Linux. Entre los ejemplos en la página de Google Coral Github hay un ejemplo llamado "serpiente auditiva" para un sistema de reconocimiento de voz que puede comprender 140 frases clave (septiembre de 2019), que luego se asignan a pulsaciones de teclas virtuales. La combinación de estas "pulsaciones de teclas" con la ejecución de algunas funciones programadas en Python hace posible construir un dispositivo controlado por comandos de voz. Recientemente había descrito una primera implementación, un gato de salto electromecánico controlado por voz. La implementación aquí es un poco más compleja y permite controlar los cuatro servos del MeArm para mover el MeArm continuamente o hacer que se mueva a una serie de valores predefinidos. puestos, o para realizar algunas tareas más complejas.

Utilizando el script proporcionado aquí como ejemplo, debería ser relativamente sencillo construir otros dispositivos controlados por voz, p. Ej. coches robóticos o unidades de tecnología de asistencia.

Suministros

  • MeArm. Usado aquí: MeArm Pi de MIME Industries
  • Frambuesa pi 4
  • Acelerador de TPU de Google Coral
  • Capó servo de 16 canales Adafruit
  • algunos cables de puente
  • opcional: condensador para el capó del servo, aproximadamente 400 µF para 4 servos (recomendado por Adafruit)
  • Fuente de alimentación de 5-6 V para el capó del servo. Aquí utilicé un cargador antiguo de 6 V, una batería 4x AA también funciona
  • Micrófono. Usé una vieja cámara web Microsoft HD3000 como micrófono.

Paso 1: configurar el sistema

Configurar el sistema
Configurar el sistema
Configurar el sistema
Configurar el sistema

Descargue la imagen de Raspian preconfigurada para Google Coral TPU Accelerator desde la página de Google Coral Github e instálela en una tarjeta µSD. La imagen también contiene varios scripts de ejemplo. Configure el Pi como se indica.

Instale el ejemplo de buscador de palabras clave del sitio de Google Coral GitHub, si no está incluido en la imagen, y todos los programas requeridos. Conecte el micrófono al Pi. Recomendaría jugar con el ejemplo de "Hearing Snake" para asegurarse de que todo funciona.

Descargue e instale el software de capó de 16 canales Adafruit, como se describe aquí. Instale el capó y juegue con los ejemplos de Adafruit para asegurarse de que todo funcione correctamente.

Descargue los archivos adjuntos a este instructivo y cópielos en la carpeta "Project Keyword Spotter". El archivo "commands_v1_MeArm.txt" debe copiarse en la subcarpeta "config".

Conecte los servos de su MeArm al capó del servo como se indica. Usé el puerto 15 para arriba / abajo, el puerto 11 para adelante / atrás, el puerto 7 para girar y el puerto 3 para los servos de agarre.

Dentro del script, es posible que deba ajustar los valores mínimo / central / máximo para cada servo a su configuración. Estos ajustes ayudan a evitar daños a los servos. También puede que tenga que modificar las listas de "posiciones", "transporte1" y "transporte2" incluidas.

Ejecute el script. Hasta ahora lo había estado ejecutando desde el IDE.

En caso de que desee modificar las frases clave que evocan una determinada función de acuerdo con su necesidad, encontrará una lista completa de las frases clave disponibles en el archivo "labels_gc2 raw.txt" en la subcarpeta de configuración.

El sistema tiene un tiempo de latencia de aproximadamente 1 segundo, pero depende mucho de las acciones que se realicen. En algunos casos, la fase clave debe repetirse, la precisión del reconocimiento no siempre es del 100%.

Paso 2: uso del dispositivo

Si todo está configurado y verificado, puede ejecutar el dispositivo.

Una limitación actual es que una orden dada se ejecuta repetidamente siempre que no se detenga (usando "detener juego") o se dé otra orden. Tareas complejas de varios pasos, p. Ej. "transport1" (evocado por la frase "lanzar juego") siempre se ejecutan hasta el paso final.

Entonces, al "girar a la derecha", el dispositivo se moverá en pequeños pasos hacia la derecha hasta que se detenga o se alcance el valor máximo preestablecido. "lanzar juego", "siguiente juego" o "start_video" iniciarán una serie de movimientos que se definen mediante listas que contienen la configuración de cada servo en un paso determinado. "Juego aleatorio" hará que el dispositivo salte de un paso a otro, elegido al azar de una lista de configuraciones.

Como puede ver en el video adjunto, construí un objeto con forma de diábolo de LEGO que puede ser recogido por el MeArm y transportado de un lugar a otro mediante un conjunto predefinido de movimientos. Puede definir sus propias funciones modificando las listas 'transport1' o 'transport2'.

Paso 3: el guión

La secuencia de comandos que se enumera aquí es una modificación del ejemplo "Hearing Snake" de "Project Keyword Spotter". El ejemplo se redujo al mínimo, luego se agregó la parte para manejar los servos, basada en el software y los ejemplos proporcionados para el capó del servo Adafruit.

El guión no se ha optimizado por ahora. Úselo bajo su propio riesgo, siéntase libre de modificar y optimizar.

Además de la secuencia de comandos de Python, está el archivo de comandos y el archivo de etiquetas utilizado. Colóquelo en la subcarpeta config.

Como se mencionó anteriormente, es posible que se requieran varios ajustes de parámetros para adaptar el script para su MeArm especial o algún otro dispositivo.

# Copyright 2019 Google LLC #

# Con licencia de Apache License, Versión 2.0 (la "Licencia"); # no puede utilizar este archivo excepto de conformidad con la Licencia. # Puede obtener una copia de la licencia en # # href = "https://www.apache.org/licenses/LICENSE-2.0" href = "https://www.apache.org/licenses/LICENSE-2.0" https://www.apache.org/licenses/LICENSE-2.0 # # A menos que lo exija la ley aplicable o se acuerde por escrito, el software # distribuido bajo la Licencia se distribuye "TAL CUAL", # SIN GARANTÍAS NI CONDICIONES DE CUALQUIER TIPO, ya sea expreso o implícito. # Consulte la Licencia para conocer el idioma específico que rige los permisos y # limitaciones de la Licencia. # El código original "listening_snake" fue modificado para una implementación para MeArm por el Dr. H. '' 'Instrucciones Mi implementación usa una Raspbery Pi 4 con un acelerador de Google Coral y un capó de servo de 16 canales Adafruit adjunto. Los servos de un MeArm (industrias MIME) se conectaron a los puertos 3, 7, 11 y 15 del capó. Para obtener más información, consulte el Instructable "Hearing MeArm". Comandos: "posición x", x = 0 a 9, mueve el dispositivo a una posición predefinida dada. "mover / subir", "mover / bajar", "ir / girar hacia adelante", "ir / girar hacia atrás", "girar / ir a la izquierda" y "girar / ir a la derecha" evocan un movimiento lento y escalonado en el dirección, "detener el juego" detiene los movimientos. "Abrir pestaña" y "Cerrar pestaña" abren o cierran la pinza. "iniciar video" evoca al dispositivo para que siga un orden preestablecido de posiciones, definido por la lista de 'posiciones'. "juego aleatorio" da como resultado un patrón aleatorio de movimientos, "detener juego" lo termina. "lanzar juego" inicia otra serie de movimientos predefinidos por la lista 'transporte1', "siguiente juego" la operación inversa predefinida por 'transporte2' Utilice bajo su propio riesgo. '' 'de _future_ import absoluta_import from _future_ import division from _future_ import print_function import argparse import os from random import randint from threading import Thread import time from edgetpu.basic.basic_engine import BasicEngine import model import pygame from pygame.locals import * import queue from importación aleatoria randrange de adafruit_servokit import ServoKit import board import busio import adafruit_pca9685 import time i2c = busio. I2C (board. SCL, board. SDA) hat = adafruit_pca9685. PCA9685 (i2c) hat.frequency = 60 kit = ServoKit (canales = 16) # establecer el número de canales # kit.servo [0].actuation_range = 160 # kit.servo [0].set_pulse_width_range (1000, 2000) # configuraciones mínimas, centrales y máximas up_l = 145 # servo arriba / abajo: arriba md_l = 95 dn_l = 45 up_r = 135 # servo adelante / atrás md_r = 90 dn_r = 50 ri_t = 30 # brazo giratorio a derecha o izquierda: posición derecha md_t = 90 # brazo giratorio a derecha o izquierda: posición central le_t = 150 op_g = 65 # pinza abierta md_g = 90 # pinza centrada cl _g = 130 # pinza cerrada vert = 15 # número de puerto del servo, servo arriba / abajo adelante = 11 # número de puerto del servo, giro del servo hacia adelante / atrás = 7 # puerto del servo para girar el agarre del servo = 3 # puerto del servo para el agarre servo # lista de ajustes del brazo para nueve posiciones position = [(md_l, md_r, md_t, op_g), (up_l, md_r, ri_t, op_g), (up_l, md_r, md_t, cl_g), (up_l, md_r, le_t, cl_g), (md_l, md_r, md_t, op_g), (md_l, md_r, md_t, md_g), (md_l, md_r, md_t, cl_g), (dn_l, dn_r, ri_t, op_g), (dn_l, dg_n, md), (dn_l, dn_r, le_t, md_g)] # define 10 posiciones base, indicadas por enteros 0-9 # procedimientos de transporte [vert / forward / turn / grip] transport1 = [(140, 70, 65, op_g), (110, 50, 65, op_g), (65, 50, 65, op_g), (65, 70, 65, cl_g), (120, 70, 65, cl_g), #get object (100, 70, 135, cl_g), (100, 80, 135, cl_g), (100, 80, 135, md_g), (100, 80, 135, op_g), (140, 70, 135, op_g), (140, 70, 90, op_g), (140, 70, 65, op_g)]

transporte2 = [(140, 70, 65, op_g), (140, 70, 135, op_g), (95, 70, 135, op_g), (95, 80, 135, op_g), (95, 80, 135, cl_g), (110, 70, 135, cl_g), (110, 70, 65, cl_g), (70, 70, 65, cl_g), (70, 70, 65, op_g), (80, 50, 65, op_g)]

dance1 = (0, 8, 7, 4, 1, 2, 3, 6, 9, 8, 5, 2, 1, 4, 7, 8, 9, 6, 3, 2, 0) # un "baile"

#movimiento de MeArm a la posición cero status = [md_l, md_r, md_t, md_g] kit.servo [vert].angle = status [0] kit.servo [forw].angle = status [1] kit.servo [turn]. angle = status [2] kit.servo [grip].angle = status [3] print (status) class Controlador (objeto): #Función de devolución de llamada def _init _ (self, q): self._q = q def callback (self, command): self._q.put (command) class Aplicación: def _init _ (self): self._running = True def on_init (self): pygame.init () self.game_started = True self._running = True return True def on_event (self, event): if event.type == pygame. QUIT: self._running = False def MeArmPos (self, keys): # conduce MeArm a posiciones preestablecidas, palabras clave: "position x" key = int (keys) p = position [key] a = p [0] b = p [1] c = p [2] d = p [3] print ("Positions:", key, "vert / forw / turn / grip:", a, "/", b, "/", c, "/", d, "grados") estado = [a, b, c, d] # documentos estado actual imprimir (estado) # sys.stdout.write ("Posición: ", tecla," izquierda / derecha: ", a," / ", b," grado ") kit.servo [vert].angle = a kit.servo [forw].angle = b kit.servo [turn].angle = c kit.servo [grip].angle = d time.sleep (0.5) def DancingMeArm (self): # controla el baile MeArm, palabra clave: "start_video" dnce = dance1 sp = (len (dnce)) para r en rango (sp): # orden de posiciones de baile, pasos sp dc = dnce [r] p = position [dc] a = p [0] b = p [1] c = p [2] d = p [3] kit.servo [vert].angle = a kit.servo [forw].angle = b kit.servo [turn].angle = c kit.servo [grip].angle = d time.sleep (1) # establece la velocidad de los movimientos time.sleep (0.5) # break al final del procedimiento def TransMeArm1 (self): # controla MeArm transport 1, palabra clave: "lanzar juego" tr1 = transport1 sp = (len (tr1)) #calcular el número de pasos para r en el rango (sp): # ir a cualquier paso p = tr1 [r] a = p [0] b = p [1] c = p [2] d = p [3] kit. servo [vert].angle = a kit.servo [forw].angle = b kit.servo [turn].angle = c kit.servo [grip].angle = d print (p) time.sleep (1) # conjuntos velocidad de los movimientos time.sleep (0.5) def TransMeArm2 (self): # controla MeArm dance, palabra clave: "siguiente juego" tr2 = transport2 sp = (len (tr2)) para r en rango (sp): # orden de posiciones de baile, pasos sp p = tr2 [r] a = p [0] b = p [1] c = p [2] d = p [3] kit.servo [vert].angle = a kit.servo [forw].angle = b kit.servo [turn].angle = c kit.servo [grip].angle = d print (p) time.sleep (1) # establece la velocidad de los movimientos time.sleep (0.5) def RandomMoves (self): # salta aleatoriamente entre posiciones predefinidas, palabra clave: "juego aleatorio" dr = randrange (9) # selecciona aleatoriamente una posición p = posición [dr] # lee parámetros de posición a = p [0] b = p [1] c = p [2] d = p [3] kit.servo [vert].angle = a kit.servo [forw].angle = b kit.servo [turn].angle = c kit.servo [grip].angle = d time.sleep (1) # establece la velocidad de los movimientos def MoveUp (auto): # levanta la pinza en pequeños pasos u0 = estado [0] # lee el estado actual u1 = u0 + 5 # más x grados if (u1 > up_l): # pruebas si no excede los parámetros min / max u1 = up_l # de lo contrario, establezca el valor min / max kit.servo [vert].angle = u1 # mover el estado del servo [0] = u1 # ajustar el valor del estado imprimir (" up ", status) time.sleep (1) # establece la velocidad def MoveDown (self): d 0 = estado [0] d1 = d0 - 5 #minus x grados if (d1 up_r): f1 = up_r kit.servo [forw].angle = f1 # move servo status [1] = f1 print ("forward", status) time.sleep (1) def MoveBack (self): b0 = status [1] b1 = b0 - 5 #minus x grados if (b1 le_t): l1 = le_t kit.servo [turn].angle = l1 # move servo status [2] = l1 print ("left", status) time.sleep (0.2) def MoveRight (self): r0 = status [2] r1 = r0 - 2 #minus x grados if (r1 <ri_t): r1 = ri_t kit.servo [turn].angle = r1 # move servo status [2] = r1 print ("right", status) time.sleep (0.2) def OpenGrip (self): kit.servo [grip].angle = op_g # establecer el grip en la posición "open": "open_tab" time.sleep (0.5) status [3] = op_g def CloseGrip (self): kit.servo [grip].angle = cl_g # establecer el grip en la posición "closed": " close_tab "time.sleep (0.5) status [3] = cl_g def StopMove (self): # no hace nada, pero detiene los movimientos print (" stop ", status) time.sleep (0.25) def spotter (self, args): engine = BasicEngine (args.model_file) mic = args.mic si args.mic es None más int (args.mic) model.classify_audio (micrófono, motor, archivo de etiquetas = "config / etiquetas_gc2.raw.txt", archivo de comandos = "config / comandos_v1_MeArm.txt", dectection_callback = self._controler.callback, sample_rate_hz = int (args.sample_rate_frames_hop), int (args.num_frames_hop)) def on_execute (self, args): si no es self.on_init (): self._running = False q = model.get_queue () self._controler = Controler (q) si no args.debug_keyboard: t = Thread (target = self.spotter, args = (args,)) t.daemon = True t.start () item = -1 while self._running: pygame.event.pump () if args.debug_keyboard: keys = pygame.key.get_pressed () else: try: new_item = q.get (True, 0.1) excepto queue. Empty: new_item = None si new_item no es None: item = new_item if (args.debug_keyboard and keys [pygame. K_ESCAPE]) o item == "stop": self._running = False # if (args.debug_keyboard and keys [pygame. K_SPACE]) o item == "go": # self. MeArmPos (7) # if (args.debug_keyboard and keys [pygame. K_RIGHT]) o item == "right": # girar a la derecha self. MoveRight () if (args.debug_ke yboard y teclas [pygame. K_LEFT]) o item == "left": # girar a la izquierda self. MoveLeft () if (args.debug_keyboard and keys [pygame. K_UP]) o item == "up": self. MoveUp () if (args.debug_keyboard y claves [pygame. K_DOWN]) o elemento == "abajo": self. MoveDown () if (args.debug_keyboard y claves [pygame. K_B]) o elemento == "b": # al revés self. MoveBack () if (args.debug_keyboard and keys [pygame. K_F]) o item == "f": # reenvía self. MoveForw () if (args.debug_keyboard and keys [pygame. K_O]) o item == "o": # agarre abierto: self. OpenGrip () if (args.debug_keyboard y claves [pygame. K_C]) o item == "c": # agarre cerrado: self. CloseGrip () if (args.debug_keyboard y claves [pygame. K_S]) o item == "s": # detener movimiento: "start_game" self. StopMove () if (args.debug_keyboard and keys [pygame. K_0]) o item == "0": self. MeArmPos (0) if (args.debug_keyboard y claves [pygame. K_1]) o elemento == "1": self. MeArmPos (1) if (args.debug_keyboard y claves [pygame. K_2]) o elemento == "2": self. MeArmPos (2) if (args.debug_keyboard y claves [pygame. K_3]) o em == "3": self. MeArmPos (3) if (args.debug_keyboard y claves [pygame. K_4]) o item == "4": self. MeArmPos (4) if (args.debug_keyboard y claves [pygame. K_5]) o elemento == "5": self. MeArmPos (5) if (args.debug_keyboard y claves [pygame. K_6]) o elemento == "6": self. MeArmPos (6) if (args.debug_keyboard y claves [pygame. K_7]) o elemento == "7": self. MeArmPos (7) if (args.debug_keyboard y claves [pygame. K_8]) o elemento == "8": self. MeArmPos (8) if (args.debug_keyboard y claves [pygame. K_9]) o elemento == "9": self. MeArmPos (9) if (args.debug_keyboard y claves [pygame. K_a]) o elemento == "d": self. DancingMeArm () #dancing MeArm, en "next_game" if (args.debug_keyboard and keys [pygame. K_r]) o item == "r": self. RandomMoves () #random dance "random game" if (args.debug_keyboard and keys [pygame. K_j]) o item == "j": self. TransMeArm1 () # objeto de transporte: "lunch_game" if (args.debug_keyboard and keys [pygame. K_k]) o item == "k": self. TransMeArm2 () # transporte dirección inversa del objeto: "next_game" '' 'if (args.debug_keyboard y keys [pygame. K_l]) o item == "l": self. JumpingJack2 (1) #LED blink "target" '' 'time.sleep (0.05) self.on_cleanup () if _name_ ==' _main_ ': parser = argparse. ArgumentParser () parser.add_argument ('- debug_keyboard', help = 'Usa el teclado para controlar el MeArm.', action = 'store_true', default = False) model.add_model_flags (parser) args = parser.parse_args () the_app = Aplicación () the_app.on_execute (args)

Recomendado: