Pybricks - nova função 'getchar' e uso RC

Para os mais especializados em mecânica e electrónica em LEGO.
Responder
Avatar do Utilizador
CyberX
Sócio
Sócio
Mensagens: 4311
Registado: 10 mar 2014, 20:09
Localização: Mira Sintra
Contacto:

Pybricks - nova função 'getchar' e uso RC

Mensagem por CyberX »

Boas.
Quem não quer ouvir falar de python, opensource, powered up hubs e caracteres especiais ASCII pode sair aqui.

Os outros: o Pybricks recebeu uma nova actualização ("minor") que inclui a função "getchar", semelhante à "input" mas non-blocking.

A função "input" é standard do python/micropython mas bloqueia a execução até ser recebido pelo stdin um carriage return. Foi trazida para o Pybricks a meu pedido e deu já muito jeito para fazer chegar comandos a um hub (como no meu Corujo que bate as asas cada vez que um mail dá entrada na Inbox) e até mesmo mas para comandar um carro como o Top Gear Rally Car ou o 4x4.

Mas esta nova função "getchar" não faz o programa parar e não espera por nada em especial. O que permite usar o próprio teclado no IDE do Pybricks (que consiste apenas no Chrome) em realtime.

Fiz uma pequena demonstração novamente com o Top Gear Rally Car - à maneira dos jogos do ZX Spectrum estou a escutar o teclado e reajo às teclas Q/A/O/P para mover o carro e a tecla R ou 0 para alinhas as rodas na posição neutra.
No video estou a usar um teclado wireless baratucho mas podia ter usado qualquer outro dispositivo HID que emule um teclado (como inclusive alguns gamepads ou o Makey Makey).



mas para quem prefere usar o telemóvel como comando, o Nordic nRF Toobox tem uma tool "UART" que permite associar "caracteres" a botões no ecrã e enviar para o hub - infelizmente cada caracter tem sempre de ser terminado por um Line Feed ou por um Carriage Return (ou ambos) o que causava problemas com o 'input' mas agora com o 'getchar' já não - basta ignorar esses caracteres.

Imagem

Mais alguns detalhes e links para o código:
https://ofalcao.pt/blog/2020/committed-to-pybricks
Jorge Pereira
«De génio, criança e louco... porquê só 1 pouco?»
Avatar do Utilizador
AVCampos
Sócio
Sócio
Mensagens: 13681
Registado: 27 fev 2007, 19:26
Localização: Barreiro
Contacto:

Re: Pybricks - nova função 'getchar' e uso RC

Mensagem por AVCampos »

QAOP... Spectrum... as recordações! ❤

Continua a ser chato é ser preciso um computador/telemóvel/whatever para fazer a ponte entre o aparelho de input e o hub; idealmente, configurar-se-ia via USB (só para EV3 e SPIKE, obviamente) o emparelhamento com o aparelho. Não sei se é possível um hub estar ligado por BT como slave a um aparelho e configurar-se como master para outro.
Avatar do Utilizador
CyberX
Sócio
Sócio
Mensagens: 4311
Registado: 10 mar 2014, 20:09
Localização: Mira Sintra
Contacto:

Re: Pybricks - nova função 'getchar' e uso RC

Mensagem por CyberX »

AVCampos Escreveu: 26 out 2020, 18:45 Continua a ser chato é ser preciso um computador/telemóvel/whatever para fazer a ponte entre o aparelho de input e o hub; idealmente, configurar-se-ia via USB (só para EV3 e SPIKE, obviamente) o emparelhamento com o aparelho. Não sei se é possível um hub estar ligado por BT como slave a um aparelho e configurar-se como master para outro.
É possível - a norma da LEGO Power Functions implementa uma "mesh"... só se "esqueceram" foi de explicar como.

O Pybricks tem essa funcionalidade (mas não usando a norma da LEGO) no roadmap para algures na versão 4. Por enquanto estamos na v3.0.9a e ainda beta (mais umas minor releases ainda até receber o Visto Gold, a documentação e os exemplos começam a aparecer mas ainda falta alguma estabilidade e meia dúzia de funionalidades incluindo um maior suporte ao SPIKE/51515).

Mas consegues usar um EV3 em vez de um computador/telemóvel/whatever. Por enquanto ainda é um bocado trapalhão mas já é qualquer coisa.
Jorge Pereira
«De génio, criança e louco... porquê só 1 pouco?»
Avatar do Utilizador
CyberX
Sócio
Sócio
Mensagens: 4311
Registado: 10 mar 2014, 20:09
Localização: Mira Sintra
Contacto:

Re: Pybricks - nova função 'getchar' e uso RC

Mensagem por CyberX »

Tal como tinha referido, é possível usar um Makey Makey:



Estou a usar a banana para a tecla "seta para cima" que é na verdade uma sequência de 3 caracteres ("ESC", "[" e "A") e uma mera garra ou crocodilo para a tecla "seta para baixo ("ESC", "[", "B")

Seguem-se outras experiências com dispositivos que geram teclas ou eventos que podem ser associados a teclas.
Jorge Pereira
«De génio, criança e louco... porquê só 1 pouco?»
Avatar do Utilizador
AVCampos
Sócio
Sócio
Mensagens: 13681
Registado: 27 fev 2007, 19:26
Localização: Barreiro
Contacto:

Re: Pybricks - nova função 'getchar' e uso RC

Mensagem por AVCampos »

"Banana for scale... I mean control." :D
Avatar do Utilizador
CyberX
Sócio
Sócio
Mensagens: 4311
Registado: 10 mar 2014, 20:09
Localização: Mira Sintra
Contacto:

Re: Pybricks - nova função 'getchar' e uso RC

Mensagem por CyberX »

E tal como referido, qualquer dispositivo que se apresente como HID pode ser utilizado.
Inclusive a Xbox Adaptive Controller com pedais e botões grandes a emular as setas do teclado:



Estou a usar o Antimicro para definir que teclas são emuladas. Supostamente também funciona em Windows por isso se alguém quiser brincar com um gamepad ou algum dispositivo HID que tenha para aí não precisa de ser fiel da Santa Igreja do Grande Pinguim
Jorge Pereira
«De génio, criança e louco... porquê só 1 pouco?»
Avatar do Utilizador
CyberX
Sócio
Sócio
Mensagens: 4311
Registado: 10 mar 2014, 20:09
Localização: Mira Sintra
Contacto:

Re: Pybricks - nova função 'getchar' e uso RC

Mensagem por CyberX »

Estou a fazer um género de tutorial de como usar a funcionalidade getchar(), usando o 42109 Top Gear Rally Car como base.

Uso sempre o mesmo script do lado do Hub mas nalguns casos, para faciitar a gravação em cima da mesa, uso um "emulador" em vez do carro propriamente dito:

Imagem

Estou a usar 2 motores XL embora no carro o motor da direção seja um L - para o código não faz qualquer diferença já que são ambos motores com tacómetro portanto a mesma classe 'Motor' funciona com ambos, sem modificação.

Código: Selecionar todos

from pybricks.hubs import TechnicHub
from pybricks.pupdevices import Motor
from pybricks.parameters import Port, Stop
from pybricks.tools import wait, StopWatch
from pybricks.experimental import getchar

SPEED_DRIVE = 100  # power applied to driving motor (percentage)
STEP_STEER  =  15  # steer direction (angle in degrees)
SPEED_STEER = 720  # speed of steer direction changes (degrees per second)
MAX_STEER   =  75  # max steer direction (angle in degrees)
                   # motor stalls if too large and program crashes

TIME_KBD    = 200  # input buffer emptying period (ms) 

# some keyboard key codes
SPACE   = 32
LWR_A   = 97

# keyboard arrow keys generate a sequence of 3 chars: ESC + '[' + A/B/C/D
ESCAPE  = 27
OBRCKT  = 91  # opening square bracket '['
CAP_A   = 65  # Arrow UP
CAP_B   = 66  # Arrow DOWN
CAP_C   = 67  # Arrow LEFT
CAP_D   = 68  # Arrow RIGHT

# clear I/O windows
for i in range(20):
    print("")
print("Running...")

hub = TechnicHub()
mDrive = Motor(Port.D)
mSteer = Motor(Port.B)
key_timer = StopWatch()

# start with steer direction pointing forward
mSteer.reset_angle(0)
angSteer = 0
mSteer.run_target(SPEED_STEER, angSteer, then=Stop.BRAKE, wait=True)

c = None
while True:
    if key_timer.time() < TIME_KBD:
        c = getchar()

        if c == ESCAPE :
            c = getchar()
            if c == OBRCKT:
                c = getchar()
                if c == CAP_A:
                    print("Move forward")
                    mDrive.dc(SPEED_DRIVE)
                    # keep moving until it's time to recycle the buffer
                elif c == CAP_B:
                    print("Move backward")
                    mDrive.dc(-SPEED_DRIVE)
                    # keep moving until it's time to recycle the buffer
                elif c == CAP_C:
                    print("Turn left")
                    if angSteer< MAX_STEER:
                        angSteer += STEP_STEER
                        mSteer.run_target(SPEED_STEER, angSteer, then=Stop.HOLD, wait=True)
                elif c == CAP_D:
                    print("Turn right")
                    if angSteer > -MAX_STEER:
                        angSteer -= STEP_STEER
                        mSteer.run_target(SPEED_STEER, angSteer, then=Stop.HOLD, wait=True)
        elif c == SPACE:
            print("Reset steer")
            angSteer = 0
            mSteer.run_target(SPEED_STEER, angSteer, then=Stop.HOLD, wait=True)

    else:
        # time to empty the input buffer
        mDrive.stop()  
        
        while True:
            c = getchar()
            if c == None:
                break
        key_timer.reset()
Começo com uma demonstração de como usar apenas o teclado directamente sobre o IDE (Chrome):



depois troco o emulador pelo carro a sério:



e depois aumento a complexidade trocando o teclado por outras coisas como o Makey Makey:



na calha um gamepad wireless, o Xbox Adaptative Controler, a app para telemóvel Nordic Toolbox e depois sabe-se lá o quê mas alguma coisa se há-de arranjar.

Sugestões são bem vindas, desde que não peçam burds.
Jorge Pereira
«De génio, criança e louco... porquê só 1 pouco?»
Responder