Tutorial · Intermediário · 35 min
Máquina de estados de coleta e colocação resistente a falhas
Implemente coleta e colocação como uma máquina de estados, com verificação da preensão e recuperação de falhas para operar sem supervisão.
Por que a demonstração funciona e o sistema não
A primeira coleta e colocação de qualquer pessoa costuma ser uma sequência de chamadas de delay(). Cada chamada bloqueia a execução por um período fixo: mova para cá, feche a garra, mova para lá, abra. Funciona em um vídeo e em cerca de 80% dos ciclos na bancada, o que parece próximo o suficiente de estar pronto.
A máquina está longe de estar pronta, porque as falhas são silenciosas. A garra fechou no vazio e o braço percorreu a mesa com a garra vazia antes de abrir sobre a caixa. A peça estava levemente inclinada e foi derrubada, sem que a preensão fosse concluída. A tensão de alimentação do servo caiu durante o levantamento e o controlador reiniciou em uma pose desconhecida, com as mandíbulas fechadas.
Uma única medida transforma esses desastres em situações recuperáveis: uma etapa de verificação entre a preensão e o levantamento, acompanhada por uma máquina de estados que tenha um caminho definido para tratar cada falha. Esse é o assunto central desta página.
Os estados
Um ciclo de coleta e colocação tem nove estados. Vale nomear todos eles, em vez de agrupar estados com funções diferentes.
| Estado | O que acontece | Condição de saída |
|---|---|---|
IDLE |
Aguarda um trabalho | Chega uma solicitação de coleta |
APPROACH |
Move o braço para uma pose acima do objeto, com a garra aberta | O braço para e se estabiliza |
DESCEND |
Executa um movimento reto para baixo até a pose de preensão | A profundidade é atingida ou um sensor de contato é acionado |
GRASP |
Fecha as mandíbulas e aguarda | O tempo de espera decorre |
VERIFY |
Verifica se há realmente uma peça segurada | Preensão confirmada → LIFT. Sem peça → RECOVER |
LIFT |
Executa um movimento reto para cima até a pose de aproximação | O braço para e se estabiliza |
TRANSFER |
Move o braço para cima do alvo de colocação | O braço para e se estabiliza |
PLACE |
Desce, abre a garra, aguarda e recua | O recuo é concluído |
RECOVER |
Abre novamente a garra, recua, conta a tentativa e tenta de novo ou desiste | Nova tentativa → APPROACH. Desistência → IDLE com uma falha |
Dois pontos de projeto fazem quase todo o trabalho aqui.
As poses de aproximação e de recuo são estados separados, acima do objeto. Uma garra que se aproxima diretamente de uma peça a partir de uma direção arbitrária pode derrubá-la. Da mesma forma, uma garra que levanta a peça ao longo de uma curva pode arrastá-la lateralmente antes de se afastar dela. Entre sempre diretamente por cima, ou diretamente ao longo do eixo de inserção, usando um pequeno trecho reto; saia da mesma forma.
VERIFY é um estado, não uma linha de código. É o único momento do ciclo em que a máquina descobre se a realidade correspondeu ao plano e precisa de um caminho definido para tratar uma falha.
Verificando a preensão
Quatro maneiras, da mais barata para a mais cara. Você quer pelo menos uma.
Verificação da posição das mandíbulas (gratuita)
Se a garra tiver alguma complacência em série, a preensão de um objeto impede que as mandíbulas cheguem à posição que alcançariam ao fechar no ar. Se você puder ler a posição das mandíbulas, compará-la com a posição de fechamento no ar indicará que há algo entre os dedos.
Em um servo de hobby comum, não é possível ler a posição — ele opera em circuito aberto. Já um servo com o cursor do potenciômetro ligado a um pino do ADC oferece essa leitura pelo custo de um fio, e a modificação leva dez minutos.
Limites: indica que há algo ali, mas não que seja o objeto correto nem que a preensão está firme.
Um microinterruptor no dedo (cerca de 50p)
Um microinterruptor de alavanca na face interna de um dedo, ligado a um pino de entrada com pull-up. Ele fecha quando a placa entra em contato com algum objeto.
Essa é a melhor opção em custo-benefício, por uma larga margem. Fornece uma resposta digital direta para “há algo entre as mandíbulas”, é robusta e pode ter as oscilações de contato tratadas em software com apenas três linhas. Coloque-o na parte complacente do dedo para que seja acionado de forma confiável com uma força repetível.
Sensamento de corrente (cerca de £2)
Um resistor shunt ou sensor Hall na alimentação do servo. Um servo que fecha no ar reduz a corrente até o valor de repouso; um servo que fecha sobre um objeto mantém uma corrente elevada.
Limites: a leitura é ruidosa, exige um limite que você precisa calibrar e se torna imprecisa quando a tensão da bateria cai. Vale a pena quando você também quer detectar esmagamento, e não apenas confirmar a preensão — uma corrente muito acima do valor esperado significa que a peça é mais dura do que se supunha ou que a garra fez uma preensão errada e prendeu o dispositivo de fixação.
Interrupção do feixe entre as mandíbulas (cerca de £1)
Um emissor infravermelho e um fototransistor atravessam a abertura entre as mandíbulas. A interrupção do feixe indica que há algo no espaço entre elas.
Limites: o sensor detecta o objeto antes de a preensão ser executada; portanto, verifica a presença, e não a preensão. Combine-o com outro sensor. É especialmente útil em máquinas que coletam objetos transparentes ou escuros, para os quais a visão por câmera encontra dificuldades.
Escrevendo a máquina de estados
O padrão é uma máquina de estados finita simples com um temporizador não bloqueante. Assim, nada no laço é interrompido por uma espera e a parada de emergência continua respondendo:
enum State { IDLE, APPROACH, DESCEND, GRASP, VERIFY, LIFT, TRANSFER, PLACE, RECOVER };
State state = IDLE;
uint32_t stateEnteredAt = 0;
uint8_t attempts = 0;
const uint8_t MAX_ATTEMPTS = 3;
const uint16_t GRASP_DWELL_MS = 350; // let the compliance settle before you trust it
const uint16_t SETTLE_MS = 250;
void enter(State next) { state = next; stateEnteredAt = millis(); }
bool elapsed(uint16_t ms) { return millis() - stateEnteredAt >= ms; }
// Debounced: one reading is a glitch, three in a row is a fact.
bool objectHeld() {
static uint8_t streak = 0;
streak = digitalRead(GRIP_SWITCH) == LOW ? min(streak + 1, 3) : 0;
return streak >= 3;
}
void loop() {
arm.update(); // non-blocking motion, every pass
gripper.update();
switch (state) {
case IDLE:
if (jobPending()) { attempts = 0; arm.moveTo(approachPose); enter(APPROACH); }
break;
case APPROACH:
gripper.open();
if (arm.arrived() && elapsed(SETTLE_MS)) { arm.moveTo(graspPose); enter(DESCEND); }
break;
case DESCEND:
if (arm.arrived()) { gripper.close(); enter(GRASP); }
break;
case GRASP:
// The dwell is not politeness. A compliant finger rings after closing,
// and reading the switch during the ring gives you a coin flip.
if (elapsed(GRASP_DWELL_MS)) enter(VERIFY);
break;
case VERIFY:
if (objectHeld()) { arm.moveTo(approachPose); enter(LIFT); }
else { enter(RECOVER); }
break;
case LIFT:
if (arm.arrived()) { arm.moveTo(placeApproach); enter(TRANSFER); }
break;
case TRANSFER:
if (arm.arrived()) { arm.moveTo(placePose); enter(PLACE); }
break;
case PLACE:
if (arm.arrived() && elapsed(SETTLE_MS)) {
gripper.open();
// Open BEFORE retreating, and retreat straight up, or you drag the part.
if (elapsed(SETTLE_MS + 200)) { arm.moveTo(placeApproach); enter(IDLE); }
}
break;
case RECOVER:
gripper.open();
if (elapsed(SETTLE_MS)) {
if (++attempts < MAX_ATTEMPTS) { arm.moveTo(approachPose); enter(APPROACH); }
else { raiseFault("grasp failed after 3 attempts"); enter(IDLE); }
}
break;
}
}
Três detalhes desse código merecem atenção:
O tempo de permanência após a preensão. Um dedo complacente pode oscilar por alguns centésimos de segundo depois de fechar. Verificar a preensão durante essa oscilação torna o resultado imprevisível. Em geral, 300–400 ms bastam; meça o tempo necessário registrando o interruptor durante um segundo após o fechamento.
Verificação com antioscilação. Uma leitura isolada do interruptor pode ser um pico de ruído. Três leituras consecutivas fornecem uma confirmação mais confiável, e o custo corresponde a apenas três iterações de um laço que roda a centenas de hertz.
Tentativas limitadas. Tentar indefinidamente pode fazer o robô passar a noite pressionando uma peça que caiu no chão uma hora antes. Limite a três tentativas e, em seguida, registre uma falha que exija a intervenção de uma pessoa.
O que fazer quando uma nova tentativa não ajuda
Tal como está implementado, RECOVER apenas tenta novamente a partir da mesma pose. Isso resolve o caso comum — a peça estava um pouco deslocada, as mandíbulas a empurraram e a segunda tentativa funciona — mas não resolve uma peça que está em outra posição. Algumas alternativas úteis, em ordem:
- Desloque a aproximação. A cada nova tentativa, desloque a pose de preensão alguns milímetros em uma pequena espiral. A mudança custa três linhas e resolve uma fração surpreendente dos casos.
- Faça uma nova leitura. Se você tiver uma câmera ou um sensor de distância, obtenha uma nova leitura, em vez de confiar na pose recebida.
- Aumente a abertura. Uma abertura das mandíbulas dimensionada exatamente para a peça nominal falha quando a peça está girada. Abra mais na nova tentativa.
- Sinalize a desistência de forma clara. Uma falha que para a máquina e informa o estado em que ela se encontrava é melhor do que uma máquina que continua operando e enche a caixa de rejeitados em silêncio.
As falhas que não são culpa da garra
Quando a coleta e a colocação são instáveis, muitas vezes o problema não está na preensão:
| Sintoma | Causa usual |
|---|---|
| Falha apenas em ciclos rápidos | Tempo de estabilização insuficiente. O braço concluiu o movimento, mas ainda está oscilando |
| Falha após vinte minutos | Aquecimento do servo. Consulte a corrente de travamento — as mandíbulas provavelmente permanecem fechadas durante todo o trajeto de retorno |
| Derruba a peça durante a aproximação | Está descendo em ângulo, em vez de descer em linha reta ao longo do eixo de inserção |
| Solta a peça durante a transferência, mas não durante a coleta | Aceleração. A preensão foi dimensionada para uma retenção estática, e o movimento exige mais força |
| Arrasta a peça ao soltá-la | Recua antes de as mandíbulas estarem totalmente abertas ou recua ao longo de uma curva |
| O controlador reinicia no meio do ciclo | A tensão de alimentação do servo cai. Separe a alimentação do servo da alimentação do restante do sistema |
| Começa a funcionar e depois deixa de funcionar gradualmente | Placas sujas. O valor de μ diminui com o acúmulo de poeira, e não há alarme para isso |
Vale observar a quarta linha, porque é a que mais parece um mistério. Uma preensão que funciona perfeitamente na bancada pode soltar a peça 40 ms após o início de um levantamento — antes de o braço ter se movido visivelmente — porque o termo de aceleração domina. O simulador de garra mostrará o instante exato para os seus números, e a correção costuma ser desacelerar o perfil de movimento, em vez de apertar mais.
Para onde ir daqui
Depois que o ciclo se torna confiável, as próximas adições que valem a pena são, em ordem de prioridade:
- Contagem de ciclos e registro de falhas. Você não pode melhorar um índice de confiabilidade que não está medindo.
- Um perfil de movimento adequado para a transferência, com aceleração limitada, para que você não precise superdimensionar a preensão apenas para resistir a movimentos bruscos.
- Pose obtida por sensores, em vez de usar valores constantes — é essa a transição de uma demonstração para uma máquina.
Próximo
- Máquinas de estados finitas para comportamento de robôs — o padrão geral do qual este é um exemplo
- Força de preensão com servo, torque de travamento e complacência — por que o tempo de espera existe e por que as mandíbulas não devem ficar fechadas
- Tipos de garras robóticas e força de preensão — o dimensionamento da preensão do qual a sequência depende
- O simulador de garra — encontre o instante em que uma preensão solta com seus próprios números
Explore o grafo
Faz parte destas montagens
Projetos e caminhos de aprendizagem que incluem este tutorial.
Leitura complementar