Desbravando o PyBricks: Programando o SPIKE Prime em Python do Zero
Aula

Objetivo da aula

  • Entender como ler a distância (em mm) usando o sensor ultrassônico.
  • Aplicar leituras para parar, manter distância e desviar de obstáculos.
  • Conhecer técnicas de suavização (média) e boas práticas de montagem para leituras estáveis.

Preparação

  • Conecte o sensor ultrassônico à porta C (ajuste no código se usar outra).
  • Motores de tração nas portas A (esquerdo) e B (direito), ou use DriveBase.
  • Altura do sensor a ~5–7 cm do piso e apontado reto para frente.

1) Primeira leitura de distância

No PyBricks, a leitura retorna milímetros (mm). Valores típicos ficam de ~50 mm até ~2000+ mm, dependendo do ambiente.

from pybricks.hubs import PrimeHub
from pybricks.pupdevices import Motor, UltrasonicSensor
from pybricks.parameters import Port, Color, Stop
from pybricks.tools import wait

hub = PrimeHub()
mE, mD = Motor(Port.A), Motor(Port.B)
us  = UltrasonicSensor(Port.C)

while True:
    d = us.distance()          # distância em mm
    if d < 200:              # objeto a menos de 20 cm
        hub.light.on(Color.RED)
    else:
        hub.light.on(Color.GREEN)
    wait(100)

2) Avançar até uma distância alvo e parar

Exemplo clássico de “aproximar e parar” (estacionar ou encostar sem bater):

alvo_mm = 180
vel = 220

mE.run(vel); mD.run(vel)

while True:
    d = us.distance()
    if d <= alvo_mm:
        mE.stop(); mD.stop()
        hub.light.on(Color.YELLOW)
        break
    wait(15)

3) Manter distância constante (controle proporcional)

O robô ajusta a velocidade para “seguir” um alvo mantendo distância alvo_mm.
Quanto maior o erro, maior a correção (ganho Kp).

alvo_mm = 200
Kp = 1.2                 # ajuste: se oscilar, diminua; se lento, aumente
v_max = 300

while True:
    d = us.distance()
    erro = d - alvo_mm       # positivo = longe demais; negativo = muito perto
    v = Kp * erro

    if v >  v_max: v =  v_max
    if v < -v_max: v = -v_max

    mE.run(v); mD.run(v)
    wait(20)

4) Integrando com DriveBase

Usando DriveBase a lógica fica mais simples e escalável para missões.

from pybricks.robotics import DriveBase

robot = DriveBase(mE, mD, 56, 120)
alvo_mm, Kp = 220, 1.0

while True:
    d = us.distance()
    v = Kp * (d - alvo_mm)
    if v > 300: v = 300
    if v < -200: v = -200

    robot.drive(v, 0)     # sem giro (reta)
    if d <= alvo_mm:
        robot.stop(Stop.BRAKE)
        break
    wait(20)

5) Desvio simples de obstáculo

Ao detectar objeto perto, o robô para de avançar, gira levemente e tenta retomar o trajeto.

limite = 180
robot.settings(straight_speed=220, turn_rate=90)

for _ in range(8):           # 8 tentativas de avanço
    if us.distance() < limite:
        robot.turn(30)       # curva de escape
    else:
        robot.straight(120)  # avança um trecho

6) Leituras mais estáveis (média móvel)

Leituras podem oscilar por superfícies reflexivas, cantos ou ruído. Uma média móvel ajuda a estabilizar.

janela = [500, 500, 500, 500]     # valores iniciais

def dist_media():
    janela.pop(0)
    janela.append(us.distance())
    return sum(janela) / len(janela)

while True:
    d = dist_media()
    # use 'd' no controle em vez de 'us.distance()' bruto
    wait(15)

7) Boas práticas de montagem e uso

  • Altura e alinhamento: sensor deve “enxergar” a frente, sem peças obstruindo o feixe.
  • Vibração: fixe bem o suporte do sensor para evitar leituras flutuantes.
  • Superfícies problemáticas: objetos muito finos/absorventes podem dar leituras maiores (ou nenhuma).
  • Multialvo: cantos e ângulos podem refletir o som de volta; dê preferência a alvos planos.
  • Limites realistas: defina mínimos/máximos de confiança (ex.: descartar < 40 mm ou > 2000 mm se incoerentes).

8) Padrões de uso no torneio (FLL)

  • Encostar com segurança: aproximar até 150–200 mm, alinhar, só então realizar o acionamento do anexo.
  • Fila/Comboios: manter distância do “alvo” (parede/peça) enquanto avança em reta guiada.
  • Confirmação dupla: antes de agir, faça duas leituras sequenciais coerentes (< 50 ms entre elas).

Erros comuns

  • Unidades: distância em mm, não em centímetros.
  • Comandos concorrentes: enviar run() em ambos os motores e também DriveBase ao mesmo tempo.
  • Ganho alto (Kp): velocidade “vai e volta”; reduza o ganho e imponha limites de saturação.
  • Sensor torto: inclinação para cima/baixo aponta para o chão/parede, gerando leituras falsas.

Atividades práticas

  1. Programe o robô para parar a 180 mm de um obstáculo com repetibilidade (±10 mm).
  2. Implemente manter distância com controle proporcional e teste diferentes Kp.
  3. Adicione a média móvel e compare a estabilidade vs. leitura bruta.
  4. (Desafio) Combine ultrassônico + color: avance mantendo 220 mm até encontrar marcador azul, então pare com Stop.HOLD.