
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 явно неведомен. Но все равно здорово получилось