Robo jogador de futebol de iniciantes. Competições no MIPT. Android, Arduino e Bluetooth

Este artigo é uma semi-sequela do trabalho de Love, Death and Robots, “A máquina baseada no Arduino controlada pelo dispositivo Android via Bluetooth é um ciclo completo”, composto por duas partes ( uma , duas ). As coisas descritas lá foram levemente modificadas, refeitas e o próprio robô de uma máquina itinerante se transformou em um jogador de futebol. Em geral, há material interessante sobre como fazê-lo.

A instrução anterior foi dividida em duas partes: software e física. Não houve muitas mudanças nas duas direções, portanto, desta vez, tudo está em uma cópia. Lembrarei brevemente por que a parte descrita é necessária, mas, para um entendimento completo, é melhor examinar as duas primeiras partes.

Parte física


Com base nos mesmos princípios descritos no primeiro artigo:

  • sanduíche do Arduino Uno e Motor Shield.
  • dois motores conectados à blindagem do motor.

E aqui estão as mudanças:

  • a parte do choque parecia, por incrível que pareça, responsável por acertar a bola.
  • o caso agora é completamente meu, impresso em uma impressora 3D.

Habitação


Um formulário é um círculo no qual se encaixam uma placa e duas rodas. Extensão para a parte onde a força de impacto ficará.



Ao projetar isso, preste atenção a:

  • Lados altos. Os robôs colidem durante o jogo, os lados protegem não apenas seus fios, mas também seus rivais.
  • Centro de gravidade e estabilidade. O centro de gravidade é, obviamente, onde está o tabuleiro. As rodas estão localizadas perto dele, para que não escorreguem. Além disso, uma bateria é colocada em cima da placa.
  • Para impedir que o robô bique no nariz ou nas costas, colocamos bolas nos amperes do kit aqui e ali (se eles não estiverem lá, você pode substituí-lo por qualquer outro design deslizante).
  • Rigidez de um design. A plataforma não deve ceder sob o peso de placas de circuito e motores. Não fure, use materiais duros (contraplacado) ou reforce a estrutura plástica com racks



E agora o principal absurdo


Bolas adicionadas por falta de "bicar" elevavam a plataforma para que as rodas não chegassem ao chão. Para evitar isso, usamos rodas de diâmetro maior ou reduzimos as estruturas de suporte. Em geral, calculamos isso com antecedência!

Peça de choque. Ela não bate. Batidas, mas não é legal o suficiente. Em nosso primeiro modelo, havia uma servomáquina à qual estava conectada uma peça semelhante a um balde de limpa-neve. Alterando a posição do servo (de 0 a 30 graus), você pode simular um golpe. Mas os servos acabaram sendo lentos, então o golpe vai para o empate.

Existem duas maneiras: adicionar um empurrão no impacto ou substituir servos por solenóides. A primeira opção é aumentar o impulso, fornecendo velocidade às rodas durante um curso. Na prática, é o seguinte: o usuário pressiona o botão de acionar, o robô começa a partir do local (ligeiramente) e, ao mesmo tempo, faz um ataque.

A segunda opção - os solenóides pressionam a parte do choque, e aqui tudo depende da potência (velocidade) do choque, que por sua vez depende das características do solenóide.



Parte do software


Por uma boa tradição, que já é um artigo, dividiremos esta seção em duas partes. Primeiro, um aplicativo Android e, em seguida, um esboço do Arduino.

Android


Deixe-me lembrá-lo, o aplicativo foi escrito por mim do zero. Nos últimos seis meses, entendi um pouco mais sobre esse assunto, então descreverei o que pensava.

Primeiro, vamos à simplificação. Agora, o protocolo de comunicação é o seguinte: “caractere de abertura” + “valor” + “caractere de fechamento” (para entender como obtenho esses valores e o que se trata, consulte a análise completa do aplicativo aqui ). Isso funciona para velocidade e ângulo. Como existe apenas um tipo de ataque, ele não precisa de tanta sabedoria, portanto o time consiste em um personagem “/” (sobre o time atingido no parágrafo).

private void sendCommand(String speed, String angle) { String speedCommand = "#" + speed + "#"; //     String angleCommand = "@" + angle + "@"; try { outputStream.write(speedCommand.getBytes()); //   outputStream.write(angleCommand.getBytes()); } catch(Exception e) { e.printStackTrace(); } } 

Um comando típico seria assim: # 125 # @ 180 @, onde 125 é velocidade e 180 é ângulo. Obviamente, isso ainda pode ser simplificado, mas uma das tarefas era manter a leveza e a legibilidade, para que mais tarde pudesse ser facilmente explicada, inclusive para as crianças.

Um novo comando sendHit () apareceu, que é acionado quando o botão "Hit" é pressionado. Ela envia um único "/". Como o bluetooth comum 2.0+ não sofre com os dados recebidos ao mesmo tempo, ou seja, sabe como colocá-los na fila e não perder, não precisamos controlar isso. Se você estiver trabalhando com o Bluetooth Low Energy 4.0+ (bem, de repente), já a fila precisará ser organizada manualmente, caso contrário, os dados serão perdidos.

 ... bHit = findViewById(R.id.b_high_hit); //   bHit.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { threadCommand.sendHit(); //     "" } }); ... private void sendHit() { try { outputStream.write("/".getBytes()); //   }catch (Exception e) { e.printStackTrace(); } } } 

Arduino


Portanto, o protocolo para enviar comandos mudou, o algoritmo de recepção também mudou. Ele simplificou. Um se o chute de rastreamento também foi adicionado. Uma análise completa do esboço está aqui .

bt.read () lê um caractere. Se for "#", os símbolos de velocidade começam. Nós os lemos até o caractere de fechamento "#" aparecer. O loop for não pode ser usado aqui, porque o comprimento da velocidade não é conhecido antecipadamente (pode ser um número de um dígito, dois ou três dígitos). O valor resultante é gravado na variável

O mesmo acontece com uma curva. Depois de ler a velocidade e o ângulo, passamos tudo para a função turn (int speed, int angle).

 void loop() { if(BTSerial.available() > 0) {//    char a = BTSerial.read(); //   if(a == '#') { //  sp=""; char b = BTSerial.read(); while( b != '#') { //   ,     sp+=b; b = BTSerial.read(); } } else if (a == '@') {//  val = ""; char b = BTSerial.read(); while(b != '@') { //    val+=b; //    b = BTSerial.read(); } turn(val.toInt(), sp.toInt()); //   ,   } else if (a == '/') { //,    Serial.println(a); servo.write(30); //  delay(150); servo.write(0); //    } lastTakeInformation = millis(); } else { if(millis() - lastTakeInformation > 150) { //     150 //  lastTakeInformation = 0; analogWrite(speedRight, 0); analogWrite(speedLeft, 0); } } delay(5); } 

A função turn () determina qual direção mover (para frente, para trás) e para onde girar (direita, esquerda, reta). A restrição if (speed> 0 && speed <70) é necessária para que o robô não diminua a velocidade se os bytes forem perdidos. Diante disso, quando aumentei a velocidade de transmissão (joguei com atrasos de 100 a 300ms entre as equipes) - às vezes o valor da velocidade não chegava e se transformava em 0, 40 (embora, por exemplo, 240 tenha sido realmente enviado). Muleta, mas funciona.
Pode ser chamado de "proteção contra fatores incontroláveis".

 void turn(int angle, int speed) { if(speed >= 0 && speed < 70) return; if(speed > 0) { digitalWrite(dirLeft, HIGH); digitalWrite(dirRight, HIGH); } else if (sp < 0) { digitalWrite(dirLeft, LOW); digitalWrite(dirRight, LOW); } if(angle > 149) { analogWrite(speedLeft, speed); analogWrite(speedRight, speed - 65); //  } else if (angle < 31) { analogWrite(speedLeft, speed - 65); //  analogWrite(speedRight, speed); } else { analogWrite(speedLeft, speed); analogWrite(speedRight, speed); } } 

Competições no MIPT em vez de um total


Com o nosso robô, fomos à competição de futebol robótico, que foi organizada e realizada no Instituto de Física e Tecnologia de Moscou, Dolgoprudny, 14/04/2019. Conseguimos chegar às finais de 1 \ 4, mas não avançamos mais.



O processo em si foi interessante para nós, mas aqui vou descrever as conclusões que conseguimos tirar olhando para o robô em campo:

  • precisa de mais poderoso. Quatro rodas ou motores mais potentes e outras rodas são desejáveis. Embora, é claro, os modelos de quatro rodas parecessem mais vantajosos
  • gestão não é alta. É necessário transferir o robô para uma curva do tanque (gire em um ponto devido às rodas girando em direções opostas), caso contrário, o raio da curva é muito grande. E, em geral, a opção com quatro setas, em vez de um círculo com velocidade proporcional, é preferível ao futebol . A opção descrita é mais adequada para corridas em que você dirige continuamente, e aqui você precisa de clareza (girei 10 graus em torno do meu eixo, apontei para a bola e pressionei o botão para a frente. velocidade ... você precisa de alguma forma combinar essa coisa).

Comentários e sugestões serão muito felizes. Nos artigos anteriores, os comentários às vezes são mais interessantes que o próprio artigo. Obrigado, Sasha e Dana pelo trabalho .

Source: https://habr.com/ru/post/pt448080/


All Articles