Joris Laurenssen взял старый манипулятор и используя телефон на базе Android и Arduino, реализовал его голосовое управление!
У манипулятора имеется свой собственный управляющий контроллер, который соединяется через порт DB-25. Сначала, Joris выяснил, что контроллер посылает команды через параллельный порт, затем он подключил Arduino и сделал так, чтобы он считывал значения от контроллера и пересылал их в последовательный порт. Это позволило ему установить довольно простой ASCII-код, используемый, для управления движением манипулятора (всего восемь наборов команд).
Далее, он написал простой скетч для Arduino который стал управлять манипулятором вместо родного контроллера.
Затем, Joris реализовал распознавание голосовых команд, которые выдавали управляющие сигналы манипулятору. Для этого, он использовал функцию распознавания речи своего телефона на базе Android (использовал Scripting Layer for Android (SL4A)) и скрипт на Python-е, чтобы интерпретировать команды и выдавать их в последовательный порт для Arduino.
демонстрационное видео — Robotic arm speech control (Joris даёт команды на голландском языке, но он наложил комментарии на английском, так что всё понятно):
http://www.youtube.com/watch?v=RaUX5g0on90
скетч управления манипулятором (считывает команды с последовательного порта и выставляет соответствующие биты на «параллельном соединении»)
const int numberOfChars = 40; const int millisToWait = 1000; byte command[numberOfChars] = {}; // define parallel port pins as arduino I/O pins const int nStrobe = 2; const int data_0 = 3; // -+ const int data_1 = 4; // | const int data_2 = 5; // | const int data_3 = 6; // |- the 8 data pins const int data_4 = 7; // | const int data_5 = 8; // | const int data_6 = 9; // | const int data_7 = 10;// -+ const int nAck = 11; const int busy = 12; const int strobeWait = 20; // time in microseconds for strobe void setup() { Serial.begin(9600); //serial connection with copmuter. 9600 bps pinMode(nStrobe, OUTPUT); // is active LOW digitalWrite(nStrobe, HIGH); // set HIGH pinMode(data_0, OUTPUT); pinMode(data_1, OUTPUT); pinMode(data_2, OUTPUT); pinMode(data_3, OUTPUT); pinMode(data_4, OUTPUT); pinMode(data_5, OUTPUT); pinMode(data_6, OUTPUT); pinMode(data_7, OUTPUT); pinMode(nAck, INPUT); // is active LOW pinMode(busy, INPUT); } void loop() { while (Serial.available()<=0){} int bytes_read = 0 ; while (bytes_read < numberOfChars){ if (Serial.available() > 0){ command[bytes_read] = Serial.read(); bytes_read ++; } } for(int n = 0; n < numberOfChars; n++){ Serial.write(command[n]); } printMessage(); Serial.println("Action complete"); } void printByte(byte inByte) { while(digitalRead(busy) == HIGH) { // wait until robotic arm can receive data } int b0 = bitRead(inByte, 0); // -+ int b1 = bitRead(inByte, 1); // | int b2 = bitRead(inByte, 2); // | int b3 = bitRead(inByte, 3); // |- convert the byte to write to 8 seperate intergers int b4 = bitRead(inByte, 4); // | int b5 = bitRead(inByte, 5); // | int b6 = bitRead(inByte, 6); // | int b7 = bitRead(inByte, 7); // -+ digitalWrite(data_0, b0); // -+ digitalWrite(data_1, b1); // | digitalWrite(data_2, b2); // | digitalWrite(data_3, b3); // |- write the 8 intergers to the data outputs digitalWrite(data_4, b4); // | digitalWrite(data_5, b5); // | digitalWrite(data_6, b6); // | digitalWrite(data_7, b7); // -+ digitalWrite(nStrobe, LOW); // strobe nStrobe to input data bits delayMicroseconds(strobeWait); digitalWrite(nStrobe, HIGH); while(digitalRead(busy) == HIGH) { Serial.print("*"); } } void printMessage() { for(int cursorPosition = 0; cursorPosition < numberOfChars; cursorPosition++) { byte character = command[cursorPosition]; Serial.print(character); printByte(character); delay(1); } printByte(10); // new line printByte(13); // carriage return Serial.println("done"); //notify computer that the action is complete }
robotArmControl.py
# This program is used on an android device using the SL4A (scripting layer # for android) package. It uses voice recognicion as input, and it sends the # command to the computer attached to the robotic arm using the telnet protocol # # Joris Laurenssen import android import sys import telnetlib import time import re program = "python sendToArduino.py" command = "" # make an variable to store the command move_value = 500 # This function makes a "sound hash" of the text def soundex(text, len=4): digits = "01230420002566012723044802" sndx = "" fc = "" text = text.upper() # replace groups of letters reps = {"QU":"KW","SCH":"SEE","KS":"XX","KX":"XX","KC":"KK","CK":"KK","DT":"TT","TD":"TT","CH":"GG","SZ":"SS","IJ":"YY"} for i,j in reps.iteritems(): text = text.replace(i,j) for c in text: if c.isalpha(): # only if c is in the alphabet if not fc: fc = c # remember first letter # convert the letter to a number in the alphabet, and look up # that position int the digits string d = digits[ord(c)-ord("A")] # remove duplicates if not sndx or (d != sndx[-1]): sndx += d sndx = fc + sndx[1:] sndx = sndx.replace("0","") # remove all the 0's (a, e, h, i, o, u, j, y) return (sndx + (len * "0"))[:len] def inSoundex(text, sound_hash): text = text.split(" ") for word in text: if soundex(word) == sound_hash: print soundex(word) return True # this function uses speech recognicion to make the command def transcribeCommand(): global command # we use the global command variable global move_value global continue_program raw_command = droid.recognizeSpeech("Spreek het commando?", None, None) print("You said: " + raw_command[1]) # verification # Check the results for keywords, and make the command string # used soundhashes: # open # O160 # dicht # D230 # rechts # R232 # links # L680 # omhoog # O620 # omlaag # O652 # pols # P520 # elleboog # E512 # schouder # S370 # basis # B220 # precisie # P722 # stop # S310 if inSoundex(raw_command[1], "O160"): # open command = "O" elif inSoundex(raw_command[1], "D230"): # dicht command = "C" elif inSoundex(raw_command[1], "P520"): # pols if inSoundex(raw_command[1], "R232"): # rechts command = "M0,0,0," + str(move_value) + "," + str(move_value) + ",0" elif inSoundex(raw_command[1], "L680"): # links command = "M0,0,0," + str(0-move_value) + "," + str(0-move_value) + ",0" elif inSoundex(raw_command[1], "O620"): # omhoog command = "M0,0,0," + str(0-move_value) + "," + str(move_value) + ",0" elif inSoundex(raw_command[1], "O652"): # omlaag command = "M0,0,0," + str(move_value) + "," + str(0-move_value) + ",0" elif inSoundex(raw_command[1], "E512"): # elleboog if inSoundex(raw_command[1], "O620"): # omhoog command = "M0,0," + str(move_value) + ",0,0,0" elif inSoundex(raw_command[1], "O652"): # omlaag command = "M0,0," + str(0-move_value) + ",0,0,0" elif inSoundex(raw_command[1], "S370") or inSoundex(raw_command[1], "S372"): # schouder if inSoundex(raw_command[1], "O620"): # omhoog command = "M0," + str(move_value) + ",0,0,0,0" elif inSoundex(raw_command[1], "O652"): # omlaag command = "M0," + str(0-move_value) + ",0,0,0,0" elif inSoundex(raw_command[1], "B220"): # basis if inSoundex(raw_command[1], "L680"): # links command = "M" + str(move_value) + ",0,0,0,0,0" elif inSoundex(raw_command[1], "R232"): # rechts command = "M" + str(0-move_value) + ",0,0,0,0,0" elif inSoundex(raw_command[1], "P722"): # precisie # get a numbet out of the string using a regex number = re.findall("[0-9]+", raw_command[1]) if number != []: droid.makeToast(number[0] ) move_value = int(number[0]) elif inSoundex(raw_command[1], "S310"): # stop continue_program = False if command == "": # if the command is empty, it did not recognice a case transcribeCommand() # repeat the voice recognicion proces droid.makeToast(command) # command verification # this function connects to the computer using telnet def telnetConnect(): tn.read_until("login: ") tn.write(user + "\n") if password: tn.read_until("Password: ", 1) tn.write(password + "\n") droid.makeToast("Verbonden met de computer.") # notify that there is a connection # send the command using telnet def telnetWrite(): global command print("python pws.py " + command + "\n") # verification tn.write(program + " " + command + "\n") print "written command to computer" # verification command = "" # clear the command for the next command def telnetEnd(): # logout and print the telnet log tn.write("exit\n") print tn.read_all() droid.makeToast("De verbinding is gesloten.") droid = android.Android() # make androiod instance # ask for the ip adress of the computer HOST = droid.dialogGetInput('IP', 'Wat is het ip adres van de computer?').result # the move value is the step widht of the robotic arm # move_value = int(droid.dialogGetInput('Stapgrootte', 'Wat is de stapgrootte?').result) # telnet account and password user = "android" password = "android" continue_program = True tn = telnetlib.Telnet(HOST) # make telnet instance telnetConnect() # connect to telnet # while the user wants to continue, listen and send commands while continue_program == True: transcribeCommand() telnetWrite() print continue_program telnetEnd()
toArduino.py
import sys import serial ser = serial.Serial('/dev/ttyUSB0', 9600) command = sys.argv[1] while len(command) < 40: command = command + " " if command > 40: command = command[0:41] print command ser.open() if ser.isOpen(): ser.write(command)
Ссылки
Robot-arm speech control
Scripting Layer for Android
LPT (IEEE 1284)
По теме
Клешня
Теперь клешня и по Bluetooth
Самые разные манипуляторы из Makeblock
uArm - открытый проект манипулятора под управлением Arduino
Roboticarm V2 - манипулятор изготовленный при помощи 3D-печати
0 комментариев на «“Голосовое управление манипулятором”»
Мда, дядьке этому оператор switch явно неведомен. Но все равно здорово получилось