Boneca do Round 6 usando Arduino Nano

Olá makers, como estão? Espero que estejam bem. Eu (Rodrigo Mesquita) e o Prof. Sandro Mesquita estávamos pensando no que escrever para vocês, até que tivemos a brilhante ideia de apresentar um projeto que o Prof. Sandro ajudou a desenvolver, sendo como um projeto mais “dinâmico”, digamos assim. Hoje iremos aprender a fazer a boneca do Round 6 usando Arduino Nano.

Para você que chegou aqui de paraquedas e se interessou pelo artigo, nós geralmente ensinamos como fazer um projeto, em que é usado no dia a dia e os incentivamos a pensar por si só em algum projeto e quem sabe mandar para nós fazermos e criarmos um artigo sobre.

O intuito deste artigo é mostrar que a robótica não se aplica somente em “máquinas que ajudam a sociedade” ou como trabalho, podemos “fazer” robótica em algo que gostamos, ou seja para o entretenimento.

Batatinha frita 1,2,3…

Você já deve ter assistido (caso tenha a idade indicada) ou ouvido falar sobre a série ou “dorama” coreano “Round 6” que ficou mundialmente conhecido e atingiu uma ótima avaliação na plataforma de streaming Netflix.

Esta série gira em torno da vida de Seong Gi-Hun que está afogado em dívidas. Ele acaba sendo convidado para participar de um jogo de sobrevivência, e caso ganhasse, receberia uma boa quantia de dinheiro que usaria para pagar suas dívidas e ajudar sua mãe e filha. Porém, este jogo de sobrevivência acaba virando um terrível pesadelo e assim segue a história.

O primeiro desafio enfrentado pelos participantes desse jogo se chama “batatinha frita 1,2,3”, na qual um robô gigante com feições de uma criança canta a musiquinha que se dá o nome da “brincadeira”, e os participantes tem que correr até a linha de chegada que fica na direção do robô, porém, quando a “boneca” terminar de cantar a música ninguém pode se mexer, caso o contrário, “perde” a brincadeira e consequentemente é desclassificado do jogo.

O projeto

Com a solicitação do Sana 2022 (evento geek anual de Fortaleza. Passaram aproximadamente 10 mil pessoas nos dois dias de evento) foi feito o projeto da “boneca” de Round 6, na qual o Walterlan Veríssimo fez a escultura do projeto, Sandro Mesquita a automação e Bianor Medeiros a parte mecânica e eletrônica.

A boneca possuía um Arduino Nano(que já usamos em vários projetos aqui no blog como o Carro controlado por Bluetooth) implantado na sua cabeça e controlado por rádio de frequência, possibilitando assim o movimento da cabeça assim como na série. Observe o esquemático de montagem do circuito eletrônico logo abaixo:

Além do Arduino Nano e o Rádio, usamos 02 sensores de fim de curso, representado pelos botões, um motor e uma ponte H de 43A para controle da cabeça.

Lista de componentes usados no projeto:

  • 01 Arduino Nano
  • 01 Motor CC
  • 01 Ponte H BTS7960 (ou outra caso você use em menor escala)
  • 01 Motor DC Alto Torque (ou outro caso você use em menor escala)
  • 01 Led vermelho
  • 01 Resistor de 330Ohm
  • 01 Módulo Receptor 433MHz Rx B6 (ou outro similar)
  • 02 Chaves Fim de Curso
  • 01 Antena
  • 01 Controle Remoto 433MHz Premium (ou outro similar)
  • 01 Fonte Chaveada 5A (ou outro similar)

Abaixo segue uma imagem da primeira montagem e testes realizados fora o corpo da boneca, o rádio se comportou de forma surpreendente, com um alcance de mais 20 metros com barreiras.

E logo em seguida o projeto montado na case, acondicionados em uma caixa Patola com vedação para proteger da umidade.

Observe que deixamos o dissipador de calor da ponte H para fora da caixa patola para evitar superaquecimento em seu interior.

Funcionamento

O projeto é simples mas tem uma lógica bem interessante, a cabeça deverá ficar parada, virada para frente, ao acionar o controle ela irá girar até tocar na chave fim de curso que está posicionada para garantir que a cabeça pare exatamente quando completar um ângulo de 180º, ou seja, totalmente virada para trás.

Ela irá ficar virada por um determinado tempo e retornar para posição de descanso, parando quando tocar na outra chave fim de curso.

Caso uma das chaves não seja acionada, o sistema entrará em alarme, sendo desarmado via controle e ficando no modo manual, onde ao apertar o botão A ela gira em um sentido ou outro e apertando o botão B ela para.

Ou seja, mesmo os sensores sendo danificados, o jogo não iria parar, pois o modo manual seria acionado.

Mergulhando no código

#include <RCSwitch.h>
RCSwitch mySwitch = RCSwitch();

#define led 5
#define MOTOR_POSITIVO    A0    //Pino do arduino que será ligado no pino 1 do BTS7960
#define MOTOR_NEGATIVO    A1    //Pino do arduino que será ligado no pino 2 do BTS7960
#define VELOCIDADE        150  //tempo (ms) que o motor ficará na mesma velocidade
#define END_STOP_ESQUERDO 3    //Cabeça na posição inicial, de repouso
#define END_STOP_DIREITO 4     //Cabeça virada, olhando para tras

bool virada = false, inicial = false, erro = false, sentido = false;
unsigned long tempoInicial = 0;
int tempoMovimento = 0;

void setup() {
  Serial.begin(9600);
  pinMode(led, OUTPUT);
  pinMode(MOTOR_POSITIVO, OUTPUT);
  pinMode(MOTOR_NEGATIVO, OUTPUT);
  pinMode(END_STOP_ESQUERDO, INPUT_PULLUP);
  pinMode(END_STOP_DIREITO, INPUT_PULLUP);
  digitalWrite(led, LOW);
  mySwitch.enableReceive(0);  // Ligue o receptor do Radio no pino 02
  tempoInicial = millis();
  Serial.println("Setup");
  inicializacao();
}
void loop() {
  //Serial.println(digitalRead(END_STOP_DIREITO));
  if (mySwitch.available()) {
    if (mySwitch.getReceivedValue() == 3851937) {
      sentido = !sentido;
      movimento(sentido);
      if (!virada or !inicial) {
        alarme();
      }
    }
    mySwitch.resetAvailable();
  }
}

void inicializacao() {
  if (!digitalRead(END_STOP_DIREITO)) {
    while (!digitalRead(END_STOP_DIREITO)) {
      digitalWrite(led, HIGH);
      analogWrite(MOTOR_POSITIVO, LOW);
      digitalWrite(MOTOR_NEGATIVO, VELOCIDADE);

      tempoMovimento = millis() - tempoInicial;
      if (tempoMovimento > 5000) {
        erro = true;
        digitalWrite(MOTOR_NEGATIVO, LOW);
        break;
      }
    }
  }
  else {
    alarme();
  }
  if (!erro) {
    virada = true;

    digitalWrite(MOTOR_NEGATIVO, LOW);
    digitalWrite(led, LOW);
    delay(2000);

    tempoInicial = millis();

    if (!digitalRead(END_STOP_ESQUERDO)) {
      while (!digitalRead(END_STOP_ESQUERDO)) {
        digitalWrite(led, HIGH);
        analogWrite(MOTOR_POSITIVO, VELOCIDADE);
        digitalWrite(MOTOR_NEGATIVO, LOW);

        tempoMovimento = millis() - tempoInicial;
        if (tempoMovimento > 5000) {
          erro = true;
          digitalWrite(MOTOR_POSITIVO, LOW);
          break;
        }
      }
    }
    else{
      alarme();
    }
    if (!erro) {
      digitalWrite(MOTOR_POSITIVO, LOW);
      digitalWrite(led, LOW);
      inicial = true;
    }
    else inicial = false;
  }
  else virada = false;
  if (!virada or !inicial) {
    alarme();
  }
}

void movimento(bool sentido) {
  tempoInicial = millis();
  tempoMovimento = 0;

  if (sentido) {
    while (!digitalRead(END_STOP_DIREITO)) {
      digitalWrite(led, HIGH);
      analogWrite(MOTOR_POSITIVO, LOW);
      digitalWrite(MOTOR_NEGATIVO, VELOCIDADE);

      tempoMovimento = millis() - tempoInicial;
      if (tempoMovimento > 5000) {
        erro = true;
        digitalWrite(MOTOR_NEGATIVO, LOW);
        break;
      }
    }
    digitalWrite(MOTOR_NEGATIVO, LOW);
    digitalWrite(led, LOW);
    if (!erro) {
      virada = true;
    }
    else virada = false;
  }
  else {
    while (!digitalRead(END_STOP_ESQUERDO)) {
      digitalWrite(led, HIGH);
      analogWrite(MOTOR_POSITIVO, VELOCIDADE);
      digitalWrite(MOTOR_NEGATIVO, LOW);

      tempoMovimento = millis() - tempoInicial;
      if (tempoMovimento > 5000) {
        erro = true;
        digitalWrite(MOTOR_POSITIVO, LOW);
        break;
      }
    }
    digitalWrite(MOTOR_POSITIVO, LOW);
    digitalWrite(led, LOW);
    if (!erro) {
      inicial = true;
    }
    else inicial = false;
  }
}

void alarme() {
  unsigned long tempoAtual = millis();
  int tempoPisca = 0;
  bool estadoLed = 0;

  while (true) {
    tempoPisca = millis() - tempoAtual;
    if (mySwitch.available()) {
      if (mySwitch.getReceivedValue() == 3851938) {
        mySwitch.resetAvailable();
        modoManual();
      }
      mySwitch.resetAvailable();
    }
    if (tempoPisca > 500) {
      digitalWrite(led, estadoLed);
      estadoLed = !estadoLed;
      tempoAtual = millis();
    }
  }
}

void modoManual() {
  sentido = false;
  bool parado = false;
  digitalWrite(led, HIGH);
  while (true) {
    if (mySwitch.available()) {
      if ((mySwitch.getReceivedValue() == 3851937) and (parado)) {
        if (sentido) {
          digitalWrite(led, HIGH);
          analogWrite(MOTOR_POSITIVO, LOW);
          digitalWrite(MOTOR_NEGATIVO, VELOCIDADE);
          parado = false;
        }
        else {
          digitalWrite(led, HIGH);
          analogWrite(MOTOR_POSITIVO, VELOCIDADE);
          digitalWrite(MOTOR_NEGATIVO, LOW);
          parado = false;
        }
      }
      else if ((mySwitch.getReceivedValue() == 3851938) and (!parado)) {
        analogWrite(MOTOR_POSITIVO, LOW);
        digitalWrite(MOTOR_NEGATIVO, LOW);
        digitalWrite(led, LOW);
        sentido = !sentido;
        parado = true;
      }
      mySwitch.resetAvailable();
    }
  }
}

Acima você encontra o código completo!

Detalhamento do código

Na primeira parte do código tem a importação da biblioteca RCSwitch (rc-switch – Arduino Libraries) para o controle do módulo receptor, definição das variáveis e no setup as devidas atualizações dos pinos e rádio.

O void loop() ficou muito enxuto, ele verifica se existe uma comunicação entre o controle e o módulo receptor (linha 30), recebe o dado do controle (linha 31) e faz a lógica de inversão do sentido de rotação da cabeça, se ela estiver virada vai para posição inicial, se estiver na posição inicial vai virar chamando a função movimento( ), caso não detecte as chaves fim de curso irá chamar a função alarme( ) e resetar a comunicação.

Sugiro copiar o código acima e olhar com detalhes na IDE do Arduino ou na IDE de sua preferência, pois o código é um pouco longo, tem 200 linhas, basicamente após o loop o código tem 04 funções:

  • void inicializacao()

Faz os testes iniciais para identificar se as chaves de fim de curso, motor e módulo receptor estão funcionando.

  • void movimento(bool sentido)

Função responsável pelo movimento automático após acionar a cabeça, ou seja, lógica de virar, aguardar um tempo e retornar.

  • void alarme()

Função responsável por parar a cabeça e acionar o modo alarme após identificar que as chaves de fim de curso estão danificadas.

  • void modoManual()

Modo de controle manual da cabeça pelo controle.

Conclusão

Esse foi o projeto da boneca do round 6 usando Arduino Nano. E assim encerramos mais um artigo, dessa vez sobre um projeto mais “informal”, abrindo assim ainda mais a mente de vocês e dando mais exemplos de projetos na qual podem ser confeccionados. Já imaginou seu projeto sendo visto por aproximadamente 10 mil pessoas em um evento como o Sana? Mas lembrem-se, com o Arduino dá para fazer projetos mais profissionais também. Não esqueçam de compartilhar conosco suas dúvidas e projetos para enriquecer ainda mais a comunidade.

Sobre Sandro Mesquita 20 artigos
Prof. Sandro Mesquita, Msc. Eng de Software, CREA - 44680 .

Seja o primeiro a comentar

Deixe uma resposta

O seu endereço de email não será publicado.


*