SerialLink#
Introdução#
O SerialLink permite que dois EXP Brains comuniquem enviando e recebendo dados brutos em série através do VEX Link. Em vez de mensagens rotuladas, o SerialLink transmite um buffer (uma string ou um array de bytes). Isto torna-o útil para comunicação avançada entre robôs, como o streaming de dados de sensores, o envio de formatos de pacotes personalizados ou a criação de protocolos próprios baseados em bytes.
Cada utilização de send adiciona dados ao buffer de recepção do EXP Brain ligado. Os dados são lidos pela ordem em que chegam (primeiro a entrar, primeiro a sair). Se forem enviados vários buffers antes de o outro EXP Brain utilizar receive, estes permanecem em fila e são devolvidos um de cada vez pela ordem em que foram enviados. Como os dados podem ser colocados em fila, o envio repetido de buffers grandes a cada loop pode criar uma acumulação; para ligações críticas em termos de tempo, envie apenas o necessário.
Importante: Ambos os robôs devem estar a executar projetos que utilizem a interface SerialLink SerialLink em simultâneo, caso contrário, não serão enviados/recebidos quaisquer dados.
Esta página utiliza o link como exemplo para o nome SerialLink -o pelo nome que configurou, se necessário.
Segue-se uma lista dos métodos disponíveis:
is_linked– Retorna se este Cérebro está ativamente ligado ao seu Cérebro emparelhado.send– Envia uma mensagem curta (com dados int/float opcionais) para o Brain emparelhado.receive– Aguarda e devolve a próxima mensagem recebida.received– Regista uma função a chamar sempre que uma nova mensagem é recebida.
Criar um link#
Crie uma interface SerialLink em ambos os EXP Brains para estabelecer um canal de comunicação entre eles — seja sem fios com os V5 Robot Radios ou através de um Smart Cable com fios — para que os robôs possam enviar dados seriais em bruto um para o outro.
SerialLink(smartport, name, linktype, wired)
Parâmetro |
Descrição |
|---|---|
|
A porta inteligente utilizada para esta ligação é a porta à qual o rádio do robô V5 está ligado (sem fios) ou à qual o cabo inteligente está ligado (com fios). Escreve-se como |
|
O nome único a atribuir a este link, em formato de texto. |
|
A função que este Cérebro desempenhará para este par de ligações. Cada par deve incluir um Gestor e um Trabalhador:
|
|
Opcional. Indica se a ligação é com ou sem fios:
|
Código para o Robot 1
""" Create a wireless link in Port 1 name: VEXRoboticsLink123456789 linktype: Manager """ link = SerialLink(Ports.PORT1, "VEXRoboticsLink123456789", VexlinkType.MANAGER)Código para o Robot 2
""" Create a wireless link in Port 1 name: VEXRoboticsLink123456789 linktype: Worker """ link = SerialLink(Ports.PORT1, "VEXRoboticsLink123456789", VexlinkType.WORKER)
Métodos disponíveis#
Após configurar o SerialLink e ligar os módulos (Brains), pode utilizar os métodos abaixo para enviar, receber e responder a dados seriais em bruto.
is_linked#
O método is_linked retorna se os módulos EXP num SerialLink estão emparelhados entre si.
True– Os dois EXP Brains estão emparelhados e a comunicar neste link.False– Os dois cérebros EXP não estão emparelhados neste link.
Nota: É uma boa prática verificar sempre se os EXP Brains estão ligados no início de um projeto antes de executar qualquer outro código.
Usage:
link.is_linked()
Parâmetros |
Descrição |
|---|---|
Este método não tem parâmetros. |
Código para o Robot 1
# Send a message to the other robot # Create the link link = SerialLink(Ports.PORT1, "VEXRoboticsLink123456789", VexlinkType.MANAGER) # Do not run code UNTIL the Brains are linked while not link.is_linked(): wait(0.1, SECONDS) brain.screen.print("Robot 1 - Manager") link.send("HELLO")Código para o Robot 2
# Display the message that Robot 1 sends # Create the link link = SerialLink(Ports.PORT1, "VEXRoboticsLink123456789", VexlinkType.WORKER) # Do not run code UNTIL the Brains are linked while not link.is_linked(): wait(0.1, SECONDS) brain.screen.print("Robot 2 - Worker") brain.screen.next_row() def received_message(bytearray, length): # Slice the bytearray to the valid data data = bytearray[:length] # Decode and strip the message before displaying it text = data.decode().strip() brain.screen.print("Got: ", text) # Call received_message whenever a message is received link.received(received_message)
send#
send que transmite bytes em série em bruto para o outro EXP Brain ligado.
Ao ler estes dados com receive, receive só retornará depois de recolher o número de bytes especificado pelo seu parâmetro length Por esta razão, se o seu código chama sempre receive com um lengthfixo, deve garantir que cada mensagem enviada com send tem exactamente esse número de bytes (geralmente por preenchimento) para que o receptor não fique bloqueado à espera de bytes adicionais.
Se não quiser depender de uma contagem exacta de bytes, utilize received em vez disso; isto permite lidar com quaisquer bytes disponíveis sem exigir um comprimento específico.
Usage:
send(buffer)
Parâmetros |
Descrição |
|---|---|
|
The data to send to the other linked EXP Brain. This can be a |
Código para o Robot 1
# Send a message to the other robot # Create the link link = SerialLink(Ports.PORT1, "VEXRoboticsLink123456789", VexlinkType.MANAGER) # Do not run code UNTIL the Brains are linked while not link.is_linked(): wait(0.1, SECONDS) brain.screen.print("Robot 1 - Manager") link.send("HELLO")Código para o Robot 2
# Display the message that Robot 1 sends # Create the link link = SerialLink(Ports.PORT1, "VEXRoboticsLink123456789", VexlinkType.WORKER) # Do not run code UNTIL the Brains are linked while not link.is_linked(): wait(0.1, SECONDS) brain.screen.print("Robot 2 - Worker") brain.screen.next_row() def received_message(bytearray, length): # Slice the bytearray to the valid data data = bytearray[:length] # Decode and strip the message before displaying it text = data.decode().strip() brain.screen.print("Got: ", text) # Call received_message whenever a message is received link.received(received_message)
receive#
receive e devolve dados em série do outro EXP Brain ligado por ordem FIFO (dados não lidos mais antigos primeiro).
Como o comando receive aguarda uma contagem exacta de bytes, as mensagens de comprimento fixo requerem frequentemente um preenchimento quando se utiliza send para que cada mensagem atinja o tamanho esperado. Se o emissor transmitir menos de length bytes, receive continuará a aguardar os restantes bytes e não devolverá nada.
Se a fila estiver vazia e fornecer um tempo limite timeout, receive receive aguardará até esse número de milissegundos por novos dados. Se nada chegar a este intervalo, devolverá None. Quaisquer dados enviados posteriormente permanecerão na fila para serem lidos mais tarde.
Usage:
receive(length, timeout)
Parâmetros |
Descrição |
|---|---|
|
O número de bytes a receber. |
|
Opcional. Tempo em milissegundos |
Código para o Robot 1
# Send a math problem for the other Brain to solve # Create the link link = SerialLink(Ports.PORT1, "VEXRoboticsLink123456789", VexlinkType.MANAGER) # Do not run code UNTIL the Brains are linked while not link.is_linked(): wait(0.1, SECONDS) brain.screen.print("Robot 1 - Manager") """ Change whether to "add" or "subtract", then what numbers to use in the operation. """ packet = "add,7,2.5" # Pad with spaces until it's exactly 16 bytes while len(packet) < 16: packet = packet + " " link.send(packet)Código para o Robot 2
# Solve the math problem that the other Brain sends # Create the link link = SerialLink(Ports.PORT1, "VEXRoboticsLink123456789", VexlinkType.WORKER) # Do not run code UNTIL the Brains are linked while not link.is_linked(): wait(0.1, SECONDS) brain.screen.print("Robot 2 - Worker") brain.screen.next_row() # Receive exactly 16 bytes buffer = link.receive(16) # Remove the added " " padding text = buffer.decode().strip() # Separate the operator and numbers parts = text.split(",") operator = parts[0] a = float(parts[1]) b = float(parts[2]) # Use what operator was sent if operator == "add": result = a + b elif operator == "subtract": result = a - b # If not "add" or "subtract", do nothing else: pass brain.screen.print("Result = ", result)
received#
O valor received regista uma função a ser chamada sempre que o EXP Brain receber dados em série.
Usage:
link.received(callback)
Parâmetros |
Descrição |
|---|---|
|
Uma função previamente definida que é executada quando o EXP Brain recebe dados em série. |
received recebidas são chamadas com dois argumentos:
Assinatura de callback:
callback(buffer, length)
Discussão |
Descrição |
|---|---|
|
Um array de bytes |
|
O número de bytes válidos recebidos no buffer |
Código para o Robot 1
# Send a message to the other robot # Create the link link = SerialLink(Ports.PORT1, "VEXRoboticsLink123456789", VexlinkType.MANAGER) # Do not run code UNTIL the Brains are linked while not link.is_linked(): wait(0.1, SECONDS) brain.screen.print("Robot 1 - Manager") link.send("HELLO")Código para o Robot 2
# Display the message that Robot 1 sends # Create the link link = SerialLink(Ports.PORT1, "VEXRoboticsLink123456789", VexlinkType.WORKER) # Do not run code UNTIL the Brains are linked while not link.is_linked(): wait(0.1, SECONDS) brain.screen.print("Robot 2 - Worker") brain.screen.next_row() def received_message(bytearray, length): # Slice the bytearray to the valid data data = bytearray[:length] # Decode and strip the message before displaying it text = data.decode().strip() brain.screen.print("Got: ", text) # Call received_message whenever a message is received link.received(received_message)