Table des matières:

Un Hearing MeArm, piloté par l'accélérateur Google Coral TPU : 3 étapes
Un Hearing MeArm, piloté par l'accélérateur Google Coral TPU : 3 étapes

Vidéo: Un Hearing MeArm, piloté par l'accélérateur Google Coral TPU : 3 étapes

Vidéo: Un Hearing MeArm, piloté par l'accélérateur Google Coral TPU : 3 étapes
Vidéo: Джордж Хотц | Программирование | tinygrad: собственный ASIC-ускоритель? мы проводим расследование с использованием реального оборудования! 2024, Juillet
Anonim
Un Hearing MeArm, piloté par l'accélérateur Google Coral TPU
Un Hearing MeArm, piloté par l'accélérateur Google Coral TPU
Un Hearing MeArm, piloté par l'accélérateur Google Coral TPU
Un Hearing MeArm, piloté par l'accélérateur Google Coral TPU
Un Hearing MeArm, piloté par l'accélérateur Google Coral TPU
Un Hearing MeArm, piloté par l'accélérateur Google Coral TPU
Un Hearing MeArm, piloté par l'accélérateur Google Coral TPU
Un Hearing MeArm, piloté par l'accélérateur Google Coral TPU

Dans ce qui suit, je voudrais décrire une version à commande vocale du MeArm, un petit bras robotique xyz avec une pince. J'ai utilisé le MeArm Pi des industries MIME, mais le système devrait être applicable à n'importe quelle version du MeArm ou à des dispositifs similaires à servocommande.

L'utilisation de Google Coral TPU Accelerator permet d'exécuter des scripts de reconnaissance vocale TensorFlow hors ligne rapides sur le Raspberry Pi, et de contrôler ainsi les appareils physiques par des ordres vocaux, avec une latence inférieure à une seconde.

Le dispositif décrit ici est une combinaison et une extension de concepts décrits dans deux instructables précédents. Il s'agit d'une extension d'une implémentation antérieure de la commande vocale Google Coral, d'un Jumping Jack, décrit ici et d'une vaste amélioration d'un MeArm à commande vocale Google AIY décrit ici.

Le MeArm à commande vocale utilisant le système Google Voice AIY nécessitait un accès en ligne, n'était pas facile à mettre en œuvre, nécessitait d'appuyer sur un bouton pour activer l'écoute des commandes vocales et avait un long temps de latence. L'accélérateur Google Coral TPU utilisé permet désormais d'exécuter des modèles TensorFlowLite hors ligne avec une vitesse élevée sur un Raspberry Pi ou d'autres appareils Linux. Parmi les exemples de la page Google Coral Github, il y a un exemple appelé "serpent auditif" pour un système de reconnaissance vocale pouvant comprendre 140 phrases clés (septembre 2019), qui sont ensuite mappées sur des frappes virtuelles. Le couplage de ces « frappes » avec l'exécution de certaines fonctions programmées en Python permet de construire un appareil contrôlé par commande vocale. J'avais récemment décrit une première implémentation, un jumping jack électromécanique à commande vocale. L'implémentation ici est un peu plus complexe et permet de contrôler les quatre servos du MeArm pour soit déplacer le MeArm en continu, soit le faire passer à un nombre prédéfini de postes ou pour effectuer des tâches plus complexes.

En utilisant le script fourni ici à titre d'exemple, il devrait être relativement simple de construire d'autres appareils à commande vocale, par ex. voitures robotisées ou unités de technologie d'assistance.

Fournitures

  • MeArm. Utilisé ici: MeArm Pi de MIME Industries
  • Framboise Pi 4
  • Accélérateur Google Coral TPU
  • Capot servo 16 canaux Adafruit
  • quelques câbles de démarrage
  • en option: condensateur pour capot de servo, environ 400 µF pour 4 servos (recommandé par Adafruit)
  • Alimentation 5-6 V pour capot servo. J'ai utilisé ici un vieux chargeur 6V, un pack de 4 piles AA fonctionne aussi
  • Microphone. J'ai utilisé une vieille webcam Microsoft HD3000 comme microphone.

Étape 1: Configuration du système

Configuration du système
Configuration du système
Configuration du système
Configuration du système

Téléchargez l'image Raspian préconfigurée pour l'accélérateur Google Coral TPU à partir de la page Google Coral Github et installez-la sur une carte µSD. L'image contient également un certain nombre d'exemples de scripts. Configurez le Pi comme indiqué.

Installez l'exemple Keyword spotter du site Google Coral GitHub, s'il n'est pas inclus dans l'image, et tous les programmes requis. Fixez le microphone au Pi. Je recommanderais de jouer avec l'exemple "Hearing Snake" pour s'assurer que tout fonctionne.

Téléchargez et installez le logiciel bonnet 16 canaux Adafruit, comme décrit ici. Installez le capot et jouez avec les exemples Adafruit pour vous assurer que tout fonctionne correctement.

Téléchargez les fichiers joints à cette instructable et copiez-les dans le dossier « Project Keyword Spotter ». Le fichier "commands_v1_MeArm.txt" doit être copié dans le sous-dossier "config".

Connectez les servos de votre MeArm au capot du servo comme indiqué. J'ai utilisé le port 15 pour le haut/bas, le port 11 pour l'avant/arrière, le port 7 pour le virage et le port 3 pour les servos de la pince.

Dans le script, vous devrez peut-être ajuster les valeurs min/centre/max de chaque servo à votre configuration. Ces paramètres permettent d'éviter d'endommager les servos. Vous devrez peut-être également modifier les listes "positions", "transport1" et "transport2" incluses.

Exécutez le script. Jusqu'à présent, je l'avais exécuté à partir de l'IDE.

Au cas où vous voudriez modifier les phrases clés qui évoquent une certaine fonction selon vos besoins. Une liste complète des phrases clés disponibles se trouve dans le fichier "labels_gc2 raw.txt" dans le sous-dossier config.

Le système a un temps de latence d'environ 1 seconde, mais dépend beaucoup des actions effectuées. Dans certains cas, la phase clé doit être répétée, la précision de la reconnaissance n'est pas toujours de 100 %.

Étape 2: Utilisation de l'appareil

Si tout est configuré et vérifié, vous pouvez exécuter l'appareil.

Une limitation actuelle est qu'un ordre donné est exécuté de manière répétitive tant qu'il n'est pas arrêté (en utilisant "stop game") ou qu'un autre ordre est donné. Tâches complexes en plusieurs étapes, par ex. "transport1" (évoqué par l'expression "launch game") sont toujours exécutés jusqu'à l'étape finale.

Ainsi, en "tournant à droite", l'appareil se déplacera par petits pas vers la droite jusqu'à ce qu'il s'arrête ou que la valeur maximale prédéfinie soit atteinte. "launch game", "next game" ou "start_video" lancera une série de mouvements définis par des listes contenant le réglage de chaque servo à une étape donnée. "jeu aléatoire" permettra à l'appareil de passer d'une étape à une autre, choisie au hasard dans une liste de paramètres.

Comme vous pouvez le voir dans la vidéo d'accompagnement, j'avais construit un objet en forme de diabolo à partir de LEGO qui peut être ramassé par le MeArm et être transporté d'un endroit à un autre par un ensemble prédéfini de mouvements. Vous pouvez définir vos propres fonctions en modifiant les listes 'transport1' ou 'transport2'.

Étape 3: le script

Le script listé ici est une modification de l'exemple "Hearing Snake" de "Project Keyword Spotter". L'exemple a été réduit au minimum, puis la partie pilotage des servos a été ajoutée, sur la base du logiciel et des exemples fournis pour le servo bonnet Adafruit.

Le script n'a pas encore été optimisé. Utilisez à vos risques et périls, n'hésitez pas à modifier et à optimiser.

En plus du script python, il y a le fichier de commandes et le fichier d'étiquettes utilisé. Placez-le dans le sous-dossier config.

Comme mentionné précédemment, plusieurs ajustements de paramètres peuvent être nécessaires pour adapter le script à votre MeArm spécial ou à un autre appareil.

# Copyright 2019 Google LLC#

# Sous licence Apache, version 2.0 (la « Licence »); # vous ne pouvez pas utiliser ce fichier sauf en conformité avec la Licence. # Vous pouvez obtenir une copie de la Licence à l'adresse # # 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 # # Sauf si requis par la loi applicable ou convenu par écrit, le logiciel # distribué sous la licence est distribué sur une BASE « TEL QUEL », # SANS GARANTIE NI CONDITIONS DE TOUT SORTE, expresse ou implicite. # Consultez la licence pour connaître les autorisations et les # limitations spécifiques à la langue en vertu de la licence. # le code original "hearing_snake" a été modifié pour une implémentation pour le MeArm par le Dr H. ''' Instructions Mon implémentation utilise un Raspbery Pi 4 avec un accélérateur Google Coral et un servo bonnet Adafruit 16 canaux attaché. Les servos d'un MeArm (MIME industries) étaient attachés aux ports 3, 7, 11 et 15 du capot. Pour plus de détails, veuillez consulter le Instructable « Hearing MeArm ». Commandes: "position x", x= 0 à 9, déplace l'appareil vers une position prédéfinie donnée. "déplacer/monter", "déplacer/descendre", "aller/tourner en avant", "aller/tourner en arrière", "tourner/aller à gauche" et "tourner/aller à droite" évoquent un mouvement lent et pas à pas dans le direction, "stop game" arrête les mouvements. "ouvrir l'onglet" et "fermer l'onglet" ouvre ou ferme la pince. "start video" évoque l'appareil pour aller suivre un ordre de positions prédéfini, défini par la liste 'positions'. « jeu aléatoire » entraîne un motif aléatoire de mouvements, « arrêter le jeu » y met fin. "launch game" démarre une autre série de coups prédéfinis par la liste 'transport1', "next game" l'opération inverse prédéfinie par 'transport2' Utilisez à vos risques et périls. ''' de _future_ import absolute_import de _future_ import division de _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 random import randrange from 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.fréquence = 60 kit = ServoKit(channels=16) # définir le nombre de canaux #kit.servo[0].actuation_range = 160 #kit.servo[0].set_pulse_width_range(1000, 2000) # paramètres min, center et max up_l = 145 # servo up/down: up md_l = 95 dn_l = 45 up_r = 135 # servo avant/arrière md_r = 90 dn_r = 50 ri_t = 30 # bras tournant à droite ou à gauche: position droite md_t = 90 # bras tournant à droite ou à gauche: position centrale le_t = 150 op_g = 65 # pince ouverte md_g = 90 # pince centrée cl _g = 130 # pince fermée vert = 15 # numéro de port servo, servo haut/bas avant = 11 # numéro de port servo, rotation avant/arrière du servo = 7 # port servo pour tourner la poignée servo = 3 # port servo pour la poignée servo #liste des réglages du bras pour neuf positions 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, dn_r, md_g), (dn_l, dn_r, le_t, md_g)] # définit 10 positions de base, indiquées par des entiers 0-9 # procédures de transport [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 objet (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)]

transport2 = [(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)]

danse1 =(0, 8, 7, 4, 1, 2, 3, 6, 9, 8, 5, 2, 1, 4, 7, 8, 9, 6, 3, 2, 0) # une "danse"

#moving MeArm to Zero position 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 Controler(object): #Callback function def _init_(self, q): self._q = q def callback(self, commande): self._q.put(command) classe App: 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): # conduit MeArm à des positions prédéfinies, mots-clés: "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, "degrees") status = [a, b, c, d] # documents status actuel print (status) # sys.stdout.write("Position: ", clé, " gauche/droite: ", a, "/", b, "degré") 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): # contrôle la danse MeArm, mot-clé: "start_video" dnce = dance1 sp=(len(dnce)) pour r dans la plage (sp): #ordre de danse des positions, pas de 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) # définit la vitesse des mouvements time.sleep(0.5) # pause à la fin de la procédure def TransMeArm1(self): # contrôle le transport MeArm 1, mot-clé: "launch game" tr1 = transport1 sp=(len(tr1)) #calculer le nombre d'étapes pour r dans la plage (sp): #aller à n'importe quelle étape 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) # ensembles vitesse des mouvements time.sleep(0.5) def TransMeArm2(self): # contrôle la danse MeArm, mot-clé: "prochain jeu" tr2 = transport2 sp=(len(tr2)) pour r dans la plage (sp): #ordre de danse des positions, sp pas 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) # définit la vitesse des mouvements time.sleep(0.5) def RandomMoves(self): # saute aléatoirement entre les positions prédéfinies, mot-clé: "random game" dr= randrange (9) #sélectionne aléatoirement une position p = position[dr] # lit les paramètres de position 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) # définit la vitesse des mouvements def MoveUp(self): # levage de la pince par petits pas u0 = status[0] # lecture de l'état actuel u1 = u0 + 5 # plus x degrés if (u1 > up_l): # teste si ne dépasse pas les paramètres min/max u1 = up_l # sinon défini sur la valeur min/max kit.servo[vert].angle = u1 # déplace le servo status[0] = u1 # ajuste la valeur d'état print (" up ", status) time.sleep (1) # définit la vitesse def MoveDown(self): d 0 = status[0] d1 = d0 - 5 #moins x degrés if (d1 up_r): f1 = up_r kit.servo[forw].angle = f1 # déplacer servo status[1] = f1 print ("forward ", status) time.sleep (1) def MoveBack(self): b0 = status[1] b1 = b0 - 5 #moins x degrés 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 #moins x degrés 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 # place la poignée en position "ouverte": "open_tab" time.sleep(0.5) status[3] = op_g def CloseGrip(self): kit.servo[grip].angle = cl_g # place la poignée en position "fermée": " close_tab" time.sleep(0.5) status[3] = cl_g def StopMove(self): # ne fait rien, mais arrête les mouvements print ("stop ", status) time.sleep(0.25) def spotter(self, args): moteur = BasicEngine(args.model_file) mic = args.mic si args.mic est None else int(args.mic) model.classify_audio(mic, engine, labels_file="config/labels_gc2.raw.txt", command_file="config/commands_v1_MeArm.txt", dectection_callback=self._controler.callback, sample_rate_hz=int(args.sample_rate_hz), num_frames_hop= int(args.num_frames_hop)) def on_execute(self, args): sinon self.on_init(): self._running = False q = model.get_queue() self._controler = Controler(q) sinon 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: essayez: new_item = q.get(True, 0.1) sauf queue. Empty: new_item = None si new_item n'est pas None: item = new_item if (args.debug_keyboard and keys[pygame. K_ESCAPE]) or item == "stop": self._running = False # if (args.debug_keyboard and keys[pygame. K_SPACE]) or item == "go": # self. MeArmPos(7) # if (args.debug_keyboard and keys [pygame. K_RIGHT]) ou item == "right": # tourner à droite self. MoveRight() if (args.debug_ke yboard et keys[pygame. K_LEFT]) ou item == "left": # tourner à gauche self. MoveLeft() if (args.debug_keyboard and keys[pygame. K_UP]) ou item == "up": self. MoveUp() if (args.debug_keyboard and keys[pygame. K_DOWN]) ou item == "down": self. MoveDown() if (args.debug_keyboard and keys[pygame. K_B]) ou item == "b": # en arrière self. MoveBack() if (args.debug_keyboard and keys[pygame. K_F]) ou item == "f": # transmet self. MoveForw() if (args.debug_keyboard and keys[pygame. K_O]) ou item == "o": # poignée ouverte: self. OpenGrip() if (args.debug_keyboard and keys[pygame. K_C]) ou item == "c": # poignée fermée: self. CloseGrip() if (args.debug_keyboard and keys [pygame. K_S]) ou item == "s": # arrêt du mouvement: "start_game" self. StopMove() if (args.debug_keyboard and keys[pygame. K_0]) ou item == "0": self. MeArmPos (0) if (args.debug_keyboard and keys[pygame. K_1]) ou item == "1": self. MeArmPos(1) if (args.debug_keyboard and keys[pygame. K_2]) ou item == "2": self. MeArmPos(2) if (args.debug_keyboard and keys[pygame. K_3]) ou il em == "3": self. MeArmPos(3) if (args.debug_keyboard and keys[pygame. K_4]) ou item == "4": self. MeArmPos(4) if (args.debug_keyboard and keys[pygame. K_5]) ou item == "5": self. MeArmPos(5) if (args.debug_keyboard and keys[pygame. K_6]) ou item == "6": self. MeArmPos(6) if (args.debug_keyboard et keys[pygame. K_7]) ou item == "7": self. MeArmPos(7) if (args.debug_keyboard and keys[pygame. K_8]) ou item == "8": self. MeArmPos(8) if (args.debug_keyboard et keys[pygame. K_9]) ou item == "9": self. MeArmPos(9) if (args.debug_keyboard and keys[pygame. K_a]) ou item == "d": self. DancingMeArm() #dancing MeArm, sur "next_game" if (args.debug_keyboard and keys[pygame. K_r]) ou item == "r": self. RandomMoves() #random dance "random game" if (args.debug_keyboard and keys[pygame. K_j]) ou item == "j": self. TransMeArm1() # objet de transport: "lunch_game" if (args.debug_keyboard and keys[pygame. K_k]) ou item == "k": self. TransMeArm2() # transport d'objet en sens inverse: "next_game" ''' if (args.debug_keyboard et keys[pygame. K_l]) ou item == "l": self. JumpingJack2(1) #LED clignotant "target" ''' time.sleep(0.05) self.on_cleanup() if _name_ == '_main_': parser = argparse. ArgumentParser() parser.add_argument('--debug_keyboard', help='Utilisez le clavier pour contrôler le MeArm.', action='store_true', default=False) model.add_model_flags(parser) args = parser.parse_args () the_app = App() the_app.on_execute(args)

Conseillé: