Disciplina de Informática Industrial Tópicos Sobre o Trabalho No....
-
Upload
truongthuan -
Category
Documents
-
view
215 -
download
0
Transcript of Disciplina de Informática Industrial Tópicos Sobre o Trabalho No....
- 1/27 -
Instituto Superior de Engenharia do Porto
Departamento de Engenharia InformáticaLicenciatura em Engenharia Informática
- Ramo de Computadores e Sistemas -
Disciplina de Informática Industrial
Tópicos Sobre o Trabalho No. 2 - Desenvolvimento de Aplicação para Controlo de
Célula de Fabrico Flexível -
Autor: Eduardo TovarData: 13/Dezembro/2002
Versão: 2.0
- 2/27 -
1. Descrição Geral do ObjectivoVisa-se o desenvolvimento de uma aplicação, em ambiente MicroSoft Windows,que permita coordenar dois equipamentos informáticos de automação industrialna prossecução de um conjunto de operações de fabrico.
Os equipamentos industriais envolvidos são:
- um robô móvel autónomo, modelo ROBUTER II do fabricante Robosoft[1];
- um manipulador robótico do tipo antropomórfico, modelo Sorbot-ERVII, do fabricante Eshed Robotec (agora Intelitek) [2].
O Robuter é um veículo de transporte automático de materiais. O Scorbot é umdispositivo de manipulação robótica. Ambos se enquadram no conjunto deequipamentos automáticos de transporte e manipulação.
O objectivo da aplicação será o de movimentar (para a frente) o Robuter. Existeuma referência no ambiente que é uma parede (obstáculo A) em direcção à qual oRobuter se irá movimentar a partir da posição inicial. Nessa direcção, o Robuterdeverá ficar a uma distância (em milímetros) previamente conhecida(dist_obst_A) do obstáculo A. Se a distância da parte lateral esquerda doRobuter ao obstáculo B for dist_obst_B (também previamente conhecida), entãopoderá ser executado pelo Scorbot um programa pré-definido de manipulação doque é transportado pelo Robuter. Finda essa manipulação, o Robuter deverárecuar até à posição inicial.
Robuter II
Scorbot ER-VII
Obstáculo_A
Obstáculo_B
Robuter II(Junto do Scorbot)
Robuter II(No Início)
dist_obs_A
dist_obs_B
Parede_C
- 3/27 -
2. Aspectos Básicos do Ambiente de DesenvolvimentoRequisitos computacionais:
- plataforma Windows98/2000/NT, MS VisualStudio (e.g. 6.0),VisualBasic;
- computador com duas portas série RS-232 (fichas DB-9 ou DB-25).
Quer o Robuter quer o Scorbot têm plataformas computacionais.
O Robuter tem um sistema computacional com o sistema operativo ALBATROS,que controla todo o hardware e dispositivos mecânicos e de sensorização. OALBATROS tem duas componentes essenciais, um interpretador de comandos eum gestor de processos. O interpretador de comandos analisa comandos enviadospelo operador ou por programas de aplicação locais. Um comando é uma mensagemASCII parametrizada seguida de um carriage return (código ASCII 13).
Um programa de aplicação é um software que pode utilizar os recursos dosistema operativo ALBATROS através de comandos ASCII ou chamadas aosistema. O sistema tem uma série de comandos pré-definidos (também podemser acrescentados outros ... API em C).
Neste trabalho irão ser utilizadas as funções de sistema já disponíveis, atravésde comandos enviados de um computador remoto via um canal de comunicações(neste caso uma porta de comunicações série RS-232). O processo é idêntico aode um terminal de um sistema UNIX...
O Scorbot tem também um sistema computacional com um sistema operativoespecífico, que controla todo o hardware e dispositivos mecânicos e desensorização. À semelhança do que acontece com o ROBUTER, irão ser utilizadasas funções de sistema já disponíveis, através de comandos enviados de umcomputador remoto via um canal de comunicações (também neste caso uma portade comunicações série RS-232). As mensagem ASCII parametrizadas (seguidasde um carriage return) são, no caso do Scorbot, comandos ACL (AdvancedControl Language).
MSWindows
Aplicação VB
Scorbot ER-VII
Robuter II
RS-232 (com1) RS-232 (com2)
PC
- 4/27 -
3. Comunicação Série (RS-232) no MS VisualBasicUma aplicação VB pode ter capacidades de comunicação série RS-232. Para oefeito deverá ser utilizado o componente Microsoft Comm Control 6.0(MSCOMM32.OCX).
Por default, o OCX para comunicações via porta série terá o nome MSComm1(MSComm2 para um segundo objecto na mesma form ...).
Um objecto MSComm tem um conjunto relativamente grande de properties.Algumas das mais importantes são:
- configuração (valores de Default)MSComm1.CommPort = 1 'COM1
MSComm1.Settings = "9600,n,8,1" '9600 bps, sem bit de paridade,
'8 data bits, 1 stop bit
MSComm1.RThreshold = 0 'número de caracteres recebidos
'no buffer de recepção
'necessários para gerar um evento
MSComm1.InputLen = 0 'número de caracteres lidos do
'buffer de recepção aquando da
'da utilização de MSComm1.Input
'se MSComm1.InputLen = 0, lê todos
'se MSComm1.InBufferCount passa a
'valer 0
'se MSComm1.InputLen = 3, lê 3
- controlonum = MSComm1.InBufferCount 'número de caracteres recebidos
'ainda não lidos
MSComm1.PortOpen = True 'activa a porta e lock do recurso
MSComm1.PortOpen = False 'desactiva e unlock do recurso
- leitura/envioMSComm1.Output = "Ola" + Chr(13) 'envio da string "ola" seguido
'de Carriage Return (ENTER)
'note que VbCr = Chr(13)
'assim como VbLf = Chr(10)
str1 = MSComm1.Input 'lê para a string str1 todos
'todos os caracteres
'existentes no buffer de recepção
'se MSComm1.InputLen = 0
- 5/27 -
Associado a um objecto MSComm existe um OnComm event. Para o objectoMSComm1, a rotina MSComm1_OnComm será chamada sempre que a propertyMSComm1.CommEvent mudar, indicando a ocorrência de um evento decomunicações ou um erro.
Exemplo da estrutura da MSComm1_On_Comm ( ):Private Sub MSComm1_OnComm ()
Select Case MSComm1.CommEvent
' Handle each event or error by placing
' code below each case statement
' Errors
Case comEventBreak ' A Break was received.
Case comEventFrame ' Framing Error
Case comEventOverrun ' Data Lost.
Case comEventRxOver ' Receive buffer overflow.
Case comEventRxParity ' Parity Error.
Case comEventTxFull ' Transmit buffer full.
Case comEventDCB ' Unexpected error retrieving DCB]
' Events
Case comEvCD ' Change in the CD line.
Case comEvCTS ' Change in the CTS line.
Case comEvDSR ' Change in the DSR line.
Case comEvRing ' Change in the Ring Indicator.
Case comEvReceive ' Received RThreshold # of chars.
Case comEvSend ' There are SThreshold number of
' characters in the transmit buffer.
Case comEvEof ' An EOF charater was found in the input stream
End Select
End Sub
Um controlo MSComm permite duas formas genéricas de lidar com ascomunicações: por eventos ou por polling.
3.1. Tratamento da Recepção por EventosNo contexto deste trabalho, o único evento relevante será o comEvReceive(relacionado com a recepção de caracteres).
- 6/27 -
Exemplo da sua utilização (eventos):Private Sub Form_Load()
MSComm1.RThreshold = 1 'activa eventos quando buffer de recepção
'recebe um caracter
MSComm1.PortOpen = True
End Sub
_______________________________________________________
Private Sub Form_Unload(Cancel As Integer)
MSComm1.PortOpen = False
End Sub
_______________________________________________________
Private Sub MSComm1_OnComm()
Text1.Text = Text1.Text + MSComm1.Input 'se MSComm1.InputLen = 0
'lê para a textbox Text1
'todos os caract. Existentes
'no buffer de recepção, e nesse
'caso, MSComm1.InputBufferCount = 0
Text1.SelStart = Len(Text1.Text) 'Text1 é uma textbox de linha
'múltipla e com scrollbar
End Sub
_______________________________________________________
Se forma mais correcta (admitindo que podem existir outro eventos - não será ocaso):_______________________________________________________
Private Sub MSComm1_OnComm()
Select Case MSComm1.CommEvent
Case comEvReceive
Text1.Text = Text1.Text + MSComm1.Input
Text1.SelStart = Len(Text1.Text)
Case Else
End Select
End Sub
____________________________________________________
- 7/27 -
Outro exemplo da utilização de eventos (uma pequena aplicação de chat, quepode ser útil para o desenvolvimento da aplicação deste trabalho - por exemplopara emular um dos dois equipamentos robóticos).
O projecto VB desta aplicação chat exemplo está disponível em [3]:
- Objectos (design phase):chat.frm
chat.MSComm1
chat.Local_Box
chat.Local_Box.ScrollBars = 2
chat.Local_Box.MultiLine = True
chat.Remote_Box
chat.Remote_Box.ScrollBars = 2
chat.Remote_Box.MultiLine = True
- CódigoPrivate Sub Form_Load()
Dim COM_No As Integer
MSComm1.RThreshold = 1
COM_No = InputBox("Introduza o Numero da Porta COM (1 ou 2):")
MSComm1.CommPort = COM_No
MSComm1.PortOpen = True
End Sub
__________________________________________________________________________
Private Sub Form_Unload(Cancel As Integer)
MSComm1.PortOpen = False
End Sub
__________________________________________________________________________
Private Sub Local_Box_KeyPress(KeyAscii As Integer)
Dim i As Integer
If KeyAscii = 13 Then
i = InStrRev(Local_Box.Text, vbLf)
MSComm1.Output = Mid(Local_Box.Text, i + 1, Len(Local_Box) - i) +
vbCrLf
End If
End Sub
__________________________________________________________________________
Private Sub MSComm1_OnComm()
Remote_Box.Text = Remote_Box.Text + MSComm1.Input
Remote_Box.SelStart = Len(Remote_Box.Text)
End Sub
- 8/27 -
3.2. Tratamento da Recepção por PollingO tratamento da recepção por polling, implica que MSComm1.RThreshold = 0.Nesse caso não será utilizada o MSComm1.On_Comm ( ).
Exemplo 1 - Variação da aplicação de chat na qual após o envio de uma linha, sefica à espera da mensagem de retorno (na qual só os primeiros 5 caracteresinteressam).
Private Sub Form_Load()
Dim COM_No As Integer
COM_No = InputBox("Introduza o Numero da Porta COM (1 ou 2):")
MSComm1.CommPort = COM_No
MSComm1.PortOpen = True
End Sub
__________________________________________________________________________
Private Sub Form_Unload(Cancel As Integer)
MSComm1.PortOpen = False
End Sub
__________________________________________________________________________
Private Sub Local_Box_KeyPress(KeyAscii As Integer)
Dim rc As String
Dim i As Integer
If KeyAscii = 13 Then
rc = MSComm1.Input ' limpa o buffer de recepção (já que
' MSComm1.InputLen = 0)
' Também dava se se fizesse MSComm1.InBufferCount = 0
i = InStrRev(Local_Box.Text, vbLf)
MSComm1.Output = Mid(Local_Box.Text, i + 1, Len(Local_Box) - i) +
vbCrLf
Local_Box.SelStart = Len(Local_Box.Text)
'fica à espera de receber a reposta (que se sabe tem 5 caracteres)
Recebe_Msg
End If
End Sub
__________________________________________________________________________
Private Sub Recebe_Msg()
Do
DoEvents
Loop Until MSComm1.InBufferCount >= 5
MSComm1.InputLen = 5 'para ler 5 primeiros caract. do buffer de recepção
Remote_Box.Text = Remote_Box.Text + MSComm1.Input
Remote_Box.SelStart = Len(Remote_Box.Text)
MSComm1.InputLen = 0
End Sub
- 9/27 -
Exemplo 2 - Variação da aplicação de chat na qual após o envio de uma linha, sefica à espera da mensagem de retorno. Na mensagem de retorno, o primeirocaracter indica o comprimento restante da mensagem.
Em relação ao código da página anterior, o que altera é a rotina Recebe_Msg ( ).Private Sub Recebe_Msg()
Dim compr As Integer
Do
DoEvents
Loop Until MSComm1.InBufferCount > 0
MSComm1.InputLen = 1
compr = Val(MSComm1.Input)
Do
DoEvents
Loop Until MSComm1.InBufferCount >= compr
MSComm1.InputLen = compr
Remote_Box.Text = Remote_Box.Text + MSComm1.Input
Remote_Box.SelStart = Len(Remote_Box.Text)
MSComm1.InputLen = 0
End Sub
Exemplo 3 - Vamos supor agora que, e por variação à versão do exemplo 2, não sesabe qual é o comprimento da mensagem de resposta. O que se sabe é que naaplicação remota ao ser enviada uma mensagem para o "PC Local" é feitoremotamente um MSComm1.Output = <mensagem>. Por isso toda a mensagem écolocada no buffer de transmissão e será enviada a uma cadência de 9600 bps.Numa abordagem "a olho", se demora 1 segundo para transmitir 9600 bits,demora cerca de 1 milisegundo para transmitir 1 caracter (8 data bits + 1 stopbit), isto é, 9 / 9600 ≈ 0.001 s = 1 ms.
Assim, em relação ao código da página anterior, o que altera-se a rotinaRecebe_Msg ( ), como indicado na página seguinte.
- 10/27 -
Private Sub Recebe_Msg()
Do ' fica à espera de receber pelo menos um caracter
DoEvents
Loop Until MSComm1.InBufferCount > 0
Do 'vai lendo tudo o que recebe enquanto MSComm1.InbufferCount > 0
DoEvents
'lê tudo o que estiver no buffer de recepção (MSComm1.InputLen = 0)
Remote_Box.Text = Remote_Box.Text + MSComm1.Input
'espera 1 ms (tempo necessário para receber mais um caracter)
'se não receber (isto é, se MSComm1.InBufferCount = 0
'é porque a mensagem acabou
Sleep (1)
Loop Until MSComm1.InBufferCount = 0
Remote_Box.SelStart = Len(Remote_Box.Text)
End Sub
Sleep é declarado na zona de declarações do código. Utilizar o API Text Viewer(Microsoft Visual Studio 6.0 Tools), fazer "load text file" de Win32api.txt, ecopiar a declaração da rotina Sleep (alterar de Public para Private):
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Se por alguma razão não é possível utilizar esta Lib, pode fazer um Sleeputilizando um Timer:
- Objecto adicional (design phase)
obviamente que pode fazer Timer1.Enabled = False no Form_Loadchat.Timer1
chat.Timer1.Enabled = False
- Código AdicionalPrivate Sub Sleep(mili As Integer)
timer_flag = True 'timer_flag é uma variável boleana global
Timer1.Interval = mili
Timer1.Enabled = True 'activa a temporização
While timer_flag
DoEvents 'é preciso, para aceitar o evento Timer_Timer ()
Wend
End Sub
__________________________________________________________________________
Private Sub Timer1_Timer()
Timer1.Enabled = False ' desactiva o Timer1, que só é activa no Sleep
timer_flag = False
End Sub
- 11/27 -
Note que na rotina da página Sleep ( ) da página anterior dentro do loop while-wend É PRECISO colocar o DoEvents, caso contrário Timer1_Timer( ) não seráexecutado quando o Timer1.Interval definido em Sleep ( ) expira.
Nota importante. O valor teórico na rotina Recebe_Msg( ) para Sleep (1 ms). Otempo de atraso imposto pela aplicação VB, pelo sistema operativo, e hardwarefaz com que um valor de 20-40 ms seja mais seguro para garantir que apropriedade MSComm1.InBufferCount seja alterada pela recepção (no buffer derecepção) de um novo caracter.
Pelo que:Private Sub Recebe_Msg()
Do ' fica à espera de receber pelo menos um caracter
DoEvents
Loop Until MSComm1.InBufferCount > 0
Do 'vai lendo tudo o que recebe enquanto MSComm1.InbufferCount > 0
DoEvents
Remote_Box.Text = Remote_Box.Text + MSComm1.Input
Sleep (30)
Loop Until MSComm1.InBufferCount = 0
Remote_Box.SelStart = Len(Remote_Box.Text)
End Sub
3.3. Notas finais sobre a comunicação série com o Robuter e o ScorbotComo já foi dito na secção 2, a interacção entre o PC onde reside a aplicação adesenvolver e os dois equipamentos será feita através do envio (e recepção) decomandos (repostas) ASCII. Qualquer um dos dois equipamentos têm uma sériede comando pré-definidos (mais detalhe na secção 4).
Alguns dos comandos a enviar aos equipamentos correspondem à recepção de umamensagem "útil". Por exemplo, um comando a "perguntar" o estado.
Por exemplo (comandos linha enviados a partir de um terminal) para umequipamento hipotético:
Prompt_Equipamento> Qual é o estado?
Estou em muito mau estado...
Prompt_Equipamento>
Para este pequeno exemplo, e utilizando um aplicação VB, o equivalente seriaenviar do PC:
MSComm1.Output = "Qual é o estado?" + Chr(13)
- 12/27 -
Note que tem de se enviar o Cariage Return (standard para delimitar o fim deuma linha de comando). Também pode ser:
MSComm1.Output = "Qual é o estado?" + VbCr
O que será recebido no buffer de recepção do MSComm1 é:"Estou em muito mau estado..." + VbCrLf + "Prompt_Equipamento>"
Ou seja:"Estou em muito mau estado..." + Chr(13) + Chr(10) + "Prompt_Equipamento>"
10 é o código ASCII do Line Feed.
Nota importante. Só é possível enviar um novo comando linha se o prompt tiversido recebido. Isto quer dizer que mesmo que um comando não tenha umaresposta específica, vai ser sempre recebida uma mensagem: o prompt. Porexemplo (e para o mesmo equipamento hipotético):
Prompt_Equipamento> Vai dar uma volta!
Prompt_Equipamento>
Na aplicação VB, isto corresponderia a enviar:MSComm1.Output = "Vai dar uma volta!" + VbCr
Após este envio, seria recebido no buffer de recepção do MSComm1 o seguinte:"Prompt_Equipamento>"
Assim, e se quisermos enviar uma sequência de três comandos (dos que não têmresposta específica) para um determinado equipamento, não se pode fazer (umaparte de uma sequência de código VB):
MSComm1.Output = "Comando 1" + Chr(13)
MSComm1.Output = "Comando 2" + Chr(13)
MSComm1.Output = "Comando 3" + Chr(13)
Mas eventualmente isto poderá resultar:MSComm1.Output = "Comando 1" + Chr(13)
Sleep (50)
MSComm1.Output = "Comando 2" + Chr(13)
Sleep (50)
MSComm1.Output = "Comando 3" + Chr(13)
Sleep (50)
Provavelmente, se a seguir a estas seis linhas de código houvesse uma instrução:Msg_lida = MSComm1.Input
e o MSComm1.InputLen = 0, a variável do tipo string Msg_lida teria o seguintevalor:
"Prompt_Equipamento>Prompt_Equipamento>Prompt_Equipamento>"
- 13/27 -
Se 50 ms não for o tempo suficiente para o equipamento "devolver" o prompt,Msg_lida poderá ser:
"ERRO..."
O mais racional é fazer:MSComm1.InBufferCount = 0 'Limpar o buffer de recepção
'para garantir que o primeiro
'Recebe_Msg irá esperar pelo
'prompt e não ira ler caracteres
'ainda não lidos
MSComm1.Output = "Comando 1" + Chr(13)
Recebe_Msg
MSComm1.Output = "Comando 2" + Chr(13)
Recebe_Msg
MSComm1.Output = "Comando 3" + Chr(13)
Recebe_Msg
Para os dois equipamentos (Robuter e Scorbot), estes conceitos são importantes.
- 14/27 -
4. Alguns Comandos Relevantes do RobuterComo será fácil de imaginar, o Robuter tem pré-definidos umas centenas decomandos, que permitem um controlo sofisticado da sua movimentação. Limitemo-nos aos mais básicos.
4.1. Comandos de Configuração BásicosOs seguintes comandos de configuração são importantes. Devem ser enviadosantes do envio de comandos de movimentação. Não há retorno específico (a nãoser em situação de erro).
MSComm1.InBufferCount = 0
MSComm1.Output = "ODOM ON" + Chr(13)
msg_in = Get_Response 'espera o prompt
MSComm1.Output = "RNOD R=ON" + Chr(13)
msg_in = Get_Response 'espera o prompt
MSComm1.Output = "MOTN ON" + Chr(13)
msg_in = Get_Response 'espera o prompt
O interpretador de comandos não é Case Sensitive, pelo queMSComm1.InBufferCount = 0
MSComm1.Output = "odom on" + Chr(13)
msg_in = Get_Response 'espera o prompt
MSComm1.Output = "rnod r=on" + Chr(13)
msg_in = Get_Response 'espera o prompt
MSComm1.Output = "motn on" + Chr(13)
msg_in = Get_Response 'espera o prompt
é também válido.
Get_Response pode ser definido da seguinte forma:Private Function Get_Response() As String
Dim msg As String
Do
DoEvents
Loop Until MSComm1.InBufferCount > 0
Do
DoEvents
msg = msg + MSComm1.Input
Sleep (30)
Loop Until MSComm1.InBufferCount = 0
Get_Response = msg
End Function
- 15/27 -
Se não houve erro na execução destes comandos na plataforma móvel, aplataforma móvel Robuter está pronta a executar movimentos básicos detranslação/rotação. Um erro pode ser detectado por inspecção da mensagemrecebida:
MSComm1.InBufferCount = 0
MSComm1.Output = "ODOM ON" + Chr(13)
msg_in = Get_Response 'espera o prompt
If InStr(msg_in, "ERR", 1) <> 0 Then
GoTo erro
End If
...
Relativamente aos comandos do Robuter.
ODOM ON/OF
Relacionado com o sistema de odometria (que permite medir distânciaspercorridas).
ODOM ON coloca o sistema de odometria a funcionar. ODOM OF desliga osistema de odometria. Deve fazer-se ODOM OF antes de fechar a aplicação.
RNOD R=ON/OF
Relacionado com o sistema de ultra-sons (que permitem ler distâncias do Robutera obstáculos).
RNOD R=ON coloca o sistema de ultra-sons a funcionar em request mode. Assim,para obter o valor da leitura de um ultra-som é preciso enviar um comandoREAD C=#,....... (ver mais tarde).
RNOD R=OF desliga o modo de request e os sensores de ultra-sons não podemser lidos. Deve fazer-se RNOD R=OF antes de fechar a aplicação.
MOTN ON/OF
MOTN ON activa o processo de controlo de movimento (família de movimentosbásicos). Outras famílias de movimentos muito mais sofisticadas são o MOTV e oMOTP.
Ao activar MOTN (MOTN ON), o Robuter está pronto a receber comandos demovimento básicos (frente, trás, esquerda e direita).
Na página seguinte está o código respeitante a esta inicialização do Robuter.
- 16/27 -
- Objectos (design phase):Robuter.frm
Robuter.MSComm1
Robuter.Local_Box
chat.Local_Box.ScrollBars = 2
chat.Local_Box.MultiLine = True
Robuter.GO
- CódigoPrivate Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Dim msg_in As String
__________________________________________________________________________
Private Sub Form_Load()
Dim COM_No As Integer
COM_No = InputBox("Introduza o Numero da Porta COM (1 ou 2):")
MSComm1.CommPort = COM_No
MSComm1.PortOpen = True
End Sub
__________________________________________________________________________
Private Sub Form_Unload(Cancel As Integer)
MSComm1.PortOpen = False
End Sub
__________________________________________________________________________
Private Sub GO_Click()
Dim dist_obst As Integer
rc = MSComm1.Input
Local_Box.Text = Local_Box.Text & "PC> " & "ODOM ON" & vbCrLf
Local_Box.SelStart = Len(Local_Box.Text)
MSComm1.Output = "ODOM ON" & vbCr
msg_in = Get_Response
Local_Box.Text = Local_Box.Text & "PC> " & "RNOD R=ON" & vbCrLf
Local_Box.SelStart = Len(Local_Box.Text)
MSComm1.Output = "RNOD R=ON" & vbCr
msg_in = Get_Response
Local_Box.Text = Local_Box.Text & "PC> " & "MOTN ON" & vbCrLf
Local_Box.SelStart = Len(Local_Box.Text)
MSComm1.Output = "MOTN ON" & vbCr
msg_in = Get_Response
End Sub
- 17/27 -
__________________________________________________________________________
Private Function Get_Response() As String
Dim msg As String
Do
DoEvents
Loop Until MSComm1.InBufferCount > 0
Do
DoEvents
msg = msg + MSComm1.Input
Sleep (30)
Loop Until MSComm1.InBufferCount = 0
Local_Box.Text = Local_Box.Text & "ROBUTER> " & msg & vbCrLf
Local_Box.SelStart = Len(Local_Box.Text)
Get_Response = msg
End Function
4.2. Comandos de MovimentaçãoSe foi executado o MOTN ON (e ODOM ON), os seguintes comandos demovimentação básicos são válidos:
- MOTN FO|BA [D=<distância em mm>] [V=<velocidade em mm/s>]
- MOTN LE|RI [A=<angulo em graus>] [V=<velocidade em graus/s>]
- MOTN KI
À semelhança dos comandos ODOM ON|OF, RNOD ON|OF e MOTN ON/OF, oscomandos MOTN FO/BA, MOTN LE/RI e MOTN KI não retornam informaçãoespecífica (só o echo da mensagem enviada, um carriage return, um line feed e oprompt) a menos que haja um erro.
Por exemplo, uma situação de erro (no caso dos comandos da família MOTN) éenviar um MOTN FO D=1000 e enviar um MOTN FO D=2000, antes do primeirodos movimento ter finalizado (andar para a frente um metro). A família decomandos de movimento MOTN não aceita queueing.
MOTN FO|BA [D=<dist>] [V=<vel>]
MOTN FO, corresponde a um movimento para a frente (forward). MOTN BA(backwards) corresponde a um movimento para trás.
Os parâmetros de distância e velocidade são opcionais. Se não se indicar adistância, o Robuter anda até receber um MOTN KI. Se não se indicar avelocidade, a velocidade de default é 100 mm/s (0.36 Km/h). A velocidademáxima é 800 mm/s (2.88 Km/h). Os valores D e V têm de ser inteiros.
- 18/27 -
MOTN LE|RI [A=<rot>] [V=<vel>]
MOTN LE, corresponde a uma rotação para a esquerda (left). MOTN RI (right)corresponde a uma rotação para direita.
Os parâmetros de rotação e velocidade são opcionais. Se não se indicar o ângulode rotação, o Robuter roda até receber um MOTN KI. Se não se indicar avelocidade, a velocidade de default é 10 graus/s. A velocidade de rotação máximaé 40 graus/s. Os valores A e V têm de ser inteiros.
MOTN KI
O comando MOTN KI aborta (kill) o movimento corrente. O Robuter para com umpequena desaceleração.
Alguns exemplos:'2 metros para a frente a 200 mm/s
MSComm1.Output = "motn fo d=2000 v=200" + Chr(13)
...
'para a frente a 200 mm/s
MSComm1.Output = "motn fo v=200" + Chr(13)
...
'para trás a 100 mm/s
MSComm1.Output = "motn ba" + Chr(13)
...
'rotação 80 graus para a esquerda a 10 graus/s
MSComm1.Output = "motn le a=80" + Chr(13)
...
4.3. Comandos de Controlo e SensorizaçãoUma capacidade importante do Robuter é o seu sistema de sensorização baseadoem 8 ultra-sons. Os ultra-sons, dispostos à volta do Robuter, permitem medir emrun-time distâncias em relação a obstáculos (ou o mundo que o rodeia). Estainformação pode ser utilizada eficientemente para navegação do veículo.
Se o comando RNOD R=ON foi executado, é possível utilizar o comandoREAD C=#,... para obter uma leitura do ultra-som #.
- 19/27 -
READ C=...
O Robuter tem uma rede de 8 ultra-sons distribuídos por seis nós.
Para ler o valor dado pelo ultra-som frontal, é preciso enviar-se o seguintecomando:
MSComm1.Output = "READ C=1,100000,100000" + Chr(13)
...
O primeiro 1 a seguir ao "=" identifica o nó de ultra-sons. Em cada nó podemestar pendurados 6 ultra-sons, o que não acontece no nó 1 (só existe 1). Por isso,coloca-se "100000" para indicar que sensores se vão ler do nó, e o segundoconjunto de "100000" indica, para cada ultra-som no nó, qual a gama de leituras:0 para distâncias relativamente pequenas (inferiores a 30cm), 1 para distânciassuperiores a 30 cm (a modo mais usual).
O retorno do comandoMSComm1.Output = "READ C=1,100000,100000" + Chr(13)
...
vai ser (no buffer de recepção):"READ C=1,100000,100000" + VbCr + VbLf + "4900 0 0 0 0 0" + VbCr + VbLf +
"Rob1.3 6.0>"
O valor da distância é 4900 / 4.9 = 1000 mm.
Dado que no nó 1 só existe 1 ultra-som, o resultado do comando:MSComm1.Output = "READ C=1,111111,111111" + Chr(13)
...
seria exactamente o mesmo.
1
3
6 2
4
5
- 20/27 -
Para ler o valor da distância a um obstáculo dado pelo ultra-som traseiro:MSComm1.Output = "READ C=4,100000,100000" + Chr(13)
...
ou lateral direito-trás:MSComm1.Output = "READ C=3,100000,100000" + Chr(13)
...
Só os ultra-sons diagonais da frente é que fazem parte de um nó com mais do queum ultra-som.
Para ler o valor do diagonal-esquerdo (mesmo nó do lateral direito-trás):MSComm1.Output = "READ C=3,010000,010000" + Chr(13)
...
e para ler o valor do diagonal-direito (mesmo nó do lateral esquero-frente):MSComm1.Output = "READ C=6,010000,010000" + Chr(13)
...
O que quer dizer que o comandoMSComm1.Output = "READ C=3,110000,110000" + Chr(13)
...
poderia retornar:"READ C=3,110000,110000" + VbCr + VbLf + "4900 9800 0 0 0 0" + VbCr + VbLf +
"Rob1.3 6.0>"
Relativamente ao comando para ler o valor do ultra-som frontal:MSComm1.Output = "READ C=1,100000,100000" + Chr(13)
...
Dado que a resposta é do tipo"READ C=1,100000,100000" + VbCr + VbLf + "11900 0 0 0 0 0" + VbCr + VbLf +
"Rob1.3 6.0>"
a informação que interessa está nos caracteres 25-29, pelo que, para processaruma leitura se pode utilizar o seguinte código (na gama de leituras elevadas, ovalor mínimo dado é 1380, isto é, tem sempre 4 caracteres):
Private Sub Ler_Ultrasom_1()
Dim u_som1 As Integer
MSComm1.Output = "READ C=1,100000,100000" & vbCr
msg_in = Get_Response
u_som1 = CInt(Val(Mid(msg_in, 25, 5)) / 4.9) 'valor em milímetros
End Sub
onde Get_Response seria como definido na página 17.
- 21/27 -
Como já foi dito antes, não se pode enviar um MOTN FO|BA|LE|RI enquanto oRobuter estiver em movimento (movimento anterior do tipo MOTN FO|BA|LE|RIainda não finalizado).
Assim, se quisermos fazer o Robuter andar para a frente 2 metros e depoisrodar para a esquerda 90º, não se pode fazer (admitindo que já foram enviadosODOM ON, RNOD R=ON e MOTN ON):
Private Sub GO_Click()
Dim dist_obst As Integer
rc = MSComm1.Input
MSComm1.Output = "MOTN FO D=2000" & vbCr
msg_in = Get_Response
MSComm1.Output = "MOTN LE A=90" & vbCr
msg_in = Get_Response
End Sub
Para verificar o estado do Robuter, utiliza-se o comando MOTN ST
MOTN ST
O comando MOTN ST retorna o estado do movimento (0 = parado; 1 = andar) e adistância (ou ângulo, se MOTN LE|RI foi o último comando de movimento)percorrido.
Por exemplo, se durante a execução de um comando MOTN FO D=2000, aconsulta do status (envio de MOTN ST) for feita, pode ser recebido no bufferde recepção:
"MOTN ST" + VbCr + VbLf + " 1 1712 " + VbCr + VbLf + "Rob1.3 6.0>"
o que quer dizer que o Robuter está a andar ("1") e relativamente ao últimocomando de movimento, já andou 1727 mílimetros.
Se se enviar um outro MOTN ST, pode ser recebido no buffer de recepção:"MOTN ST" + VbCr + VbLf + " 0 2001 " + VbCr + VbLf + "Rob1.3 6.0>"
o que quer dizer que o Robuter está parado ("1") e relativamente ao últimocomando de movimento, andou 2001 mílimetros. Isto quer dizer que o Robuter jáexecutou o comando.
Note que a informação de estado corresponde ao caracter 11 da resposta aoMOTN ST (existe um espaço antes). A informação de distância percorrida estáseparada da informação de estado por um número variável de espaços.
- 22/27 -
Assim, para executar a sequência de movimentos referida na página anterior, ocódigo deverá ser:
Private Sub GO_Click()
Dim dist_obst As Integer
rc = MSComm1.Input
MSComm1.Output = "MOTN FO D=2000" & vbCr
msg_in = Get_Response
Sleep (1000) 'dá tempo a que o Robuter começe de facto a andar
Get_Status
MSComm1.Output = "MOTN LE A=90" & vbCr
msg_in = Get_Response
Sleep (1000) 'dá tempo a que o Robuter começe de facto a andar
Get_Status
End Sub
Em que Get_Status é como se define a seguir.Private Sub Get_Status()
Dim status As Integer
' envia MOTN ST: pedido de leitura do estado do ÚLTIMO movimento MOTN
MSComm1.Output = "MOTN ST" & vbCr
status = Mid(Get_Response, 11, 1)
While status
' envia MOTN ST: pedido de leitura do estado do ÚLTIMO movimento MOTN
MSComm1.Output = "MOTN ST" & vbCr
status = Mid(Get_Response, 11, 1)
Wend
End Sub
Obviamente que o Sleep (1000) antes de testar o status pode ser substituído porum teste de quando o Robuter começa a andar (atenção que se se enviar umMOTN FO|BA D=0 ou um MOTN LE|RI A=0 o estado nunca muda para "1").Nesse caso, a rotina Get_Status seria:
- 23/27 -
Private Sub Get_Status()
Dim status As Integer
' fica à espera que o estado mude para 1
MSComm1.Output = "MOTN ST" & vbCr
status = Mid(Get_Response, 11, 1)
While (status = 0)
MSComm1.Output = "MOTN ST" & vbCr
status = Mid(Get_Response, 11, 1)
Wend
' fica à espera que o estado mude para 0
MSComm1.Output = "MOTN ST" & vbCr
status = Mid(Get_Response, 11, 1)
While status
MSComm1.Output = "MOTN ST" & vbCr
status = Mid(Get_Response, 11, 1)
Wend
End Sub
Durante o teste de estado (quando o estado = 1), poderia ser feita uma leitura deum ultra-som (cujo número depende do movimento em execução), para detectar apresença de obstáculos temporários (por exemplo, alguém se coloca à frente doRobuter). Se isso acontecer, pode utilizar-se o MOTN KI.
Após o MOTN KI, e quando o MOTN ST der estado "0" (parado), o valordistância percorrida pode ser útil para retomar a movimentação.
- 24/27 -
5. Partes da Aplicação para o Robuter [4]Relativamente à movimentação do Robuter, conforme indicado na figura da página2, antes de ele andar para a frente, deverá ser feita uma correcção doparalelismo em relação à Parede_C. Para o efeito, deverão ser utilizados os ultra-sons 2 e 3. A partir do seu valor, e sabendo que os dois ultra-sons distam entreeles 800 mm, é fácil determinar o ângulo de rotação e fazer as correcções doparalelismo em relação à parede lateral. Este é o passo 1 do programa no que dizrespeito ao Robuter (para além dos três comando de inicialização):
Private Sub Execute_Step_1()
Dim u_som2, u_som3, angulo As Integer
PI = 3.1415
MSComm1.Output = "READ C=2,100000,100000" & vbCr
msg_in = Get_Response
u_som2 = CInt(Val(Mid(msg_in, 25, 5)) / 4.9)
MSComm1.Output = "READ C=3,100000,100000" & vbCr
msg_in = Get_Response
u_som3 = CInt(Val(Mid(msg_in, 25, 5)) / 4.9)
angulo = Abs(CInt(Atn((u_som2 - u_som3) / 4.9 / 800) * 180 / PI))
While angulo > 0
If u_som2 > u_som1 Then
MSComm1.Output = "MOTN RI A=" & angulo & vbCr
msg_in = Get_Response
Else
MSComm1.Output = "MOTN LE A=" & angulo & vbCr
msg_in = Get_Response
End If
Sleep (1000) 'dá tempo a que o ROBUTER comece de facto a rodar
Get_Status 'ROTINA que vai verificar o fim de execução do movimento
MSComm1.Output = "READ C=2,100000,100000" & vbCr
msg_in = Get_Response
u_som2 = CInt(Val(Mid(msg_in, 25, 5)) / 4.9)
MSComm1.Output = "READ C=3,100000,100000" & vbCr
msg_in = Get_Response
u_som3 = CInt(Val(Mid(msg_in, 25, 5)) / 4.9)
angulo = Abs(CInt(Atn((u_som2 - u_som3) / 4.9 / 800) * 180 / PI))
Wend
End Sub
- 25/27 -
Ainda relativamente aos objectivos descritos no início, o segundo passo serádeslocar-se para a frente até ficar a uma determinada distância da paredefrontal (obstáculo frontal):Private Sub Execute_Step_2()
MSComm1.Output = "READ C=1,100000,100000" & vbCr
msg_in = Get_Response
dist = CInt(Val(Mid(msg_in, 25, 5)) / 4.9) - Val(Dist_ObA_par.Text)
While Abs(dist) > Erro_Frontal.Text
If dist > 0 Then
MSComm1.Output = "MOTN FO D=" & dist & vbCr
msg_in = Get_Response
Else
MSComm1.Output = "MOTN BA D=" & -dist & vbCr
msg_in = Get_Response
End If
Sleep (1000) 'dá tempo a que o ROBUTER comece de facto a andar
Get_Status 'ROTINA que vai verificar o fim de execução do movimento
MSComm1.Output = "READ C=1,100000,100000" & vbCr
msg_in = Get_Response
dist = CInt(Val(Mid(msg_in, 25, 5)) / 4.9) - Val(Dist_ObA_par.Text)
Wend
End Sub
- 26/27 -
6. Alguns Comandos Relevantes do Scorbot
- 27/27 -
7. Referências[1] http://www.robosoft.fr
[2] http://www.eshed.com
[3] http://www.dei.isep.ipp.pt/~emt/infind/chat.zip
[4] http://www.dei.isep.ipp.pt/~emt/infind/robuter.zip