Curso Robótica – #4 – Primeira Programação
Se o nosso robot já estiver em 3 rodas, podemos levar com segurança a parte principal do curso ou a programação. Nós não vamos usar uma biblioteca pronta, vamos escrever tudo junto de um esboço vazio. Graças a isso, os problemas descritos podem ser facilmente aplicados a outros projetos.
Também vamos lidar com um problema frequente que surge quando construímos os primeiros robots.
Nesta fase, presumo que todos já se familiarizaram com a shield usada, que descrevi na segunda parte deste curso. Além do mais, ao lado do seu computador já deve ter um robot complexo que está pronto para a programação.
O curso se concentrará na construção e programação de robots , portanto, não há espaço para descrição dos fundamentos do Arduino. Pessoas que terão problemas com o básico da programação tentarão se referir aos locais apropriados do curso Arduino.
Para não danificar o robot e dirigir…
Antes de o robot se mover, vale a pena implementar alguns hábitos que reduzirão significativamente a chance de danos à estrutura. Durante a programação, desconecte a fonte de alimentação das unidades (usando o jumper apropriado no eixo). Graças a este robot, entre outros ele não vai cair da mesa…
Para desconectar a fonte de alimentação, simplesmente remova o jumper acima.
Você não precisa traduzi-lo para a posição OFF.
Com o jumper de alimentação do drive na posição ON (e a fonte de alimentação ligada),
o díodo descrito como MOT deve estar na placa.
Tente evitar situações em que as rodas do robot estejam bloqueadas. Especificamente, trata-se de situações em que fornecemos eletricidade aos motores, mas nada acontece bloqueando as rodas. Isso pode acontecer quando mantemos o robot atrás das rodas e bloqueamos o movimento com a mão ou, por exemplo, quando ele embate num obstáculo enquanto dirigimos, e ele tentará “entrar na parede” o tempo todo.
Esta situação é perigosa por dois motivos. Em primeiro lugar, danos mecânicos de rodas, motores e engrenagens são possíveis. Em segundo lugar, quando os motores são parados , a corrente que eles puxam aumenta ligeiramente, o que pode levar ao super aquecimento do sistema de controle do inversor.
O fabricante declara que o sistema possui proteções internas que devem protegê-lo.
No entanto, há sempre um risco – é melhor evitar tais situações.
Upload seguro de um novo programa
Ao fazer download dos programas, tente seguir os passos abaixo:
- Remova o jumper de energia da unidade.
- Conecte o cabo USB e ligue a energia com o interruptor.
- Carregue um novo programa.
- Desconecte o cabo USB.
- Desligue a energia.
- Configure o jumper de energia da unidade.
- Coloque o robot no chão.
- Ligue a energia.
A situação mais perigosa é o cabo USB conectado, o jumper de energia do inversor e a
fonte de alimentação desligada pelo comutador. Então os motores serão alimentados pela
porta USB, o que pode danificar o robô e o computador!
Controle de motor usando a ponte H (DRV8835)
O nosso Arduino pode controlar os motores usando o sistema intermediário – a ponte H. Os motores consomem muita corrente para que possam ser conectados com segurança ao microcontrolador.
As noções básicas descritas neste artigo ainda são válidas, mas a ponte (DRV8835) usada aqui requer um controle diferente e mais simples. A nossa shield conecta a ponte H ao Arduino apenas com 4 sinais. Dois deles são responsáveis pela direção de rotação e os outros pela velocidade dos motores:
- O pino 4 é responsável pela direção de rotação do motor esquerdo.
- O pino 5 (PWM) é responsável pela velocidade do motor esquerdo.
- O pino 6 (PWM) é responsável pela velocidade do motor direito.
- O pino 9 é responsável pela direção de rotação do motor direito.
O princípio de funcionamento para motores individuais é o seguinte:
Por exemplo, girando o motor esquerdo para a frente à velocidade necessária XX:
- configurações na saída 4 do sinal 0,
- configurações no pino nº 5 do sinal PWM com preenchimento XX.
Girar o mesmo mecanismo de volta exigiria o seguinte controle:
- configurações na saída 4 do sinal 1,
- configurações no pino nº 5 do sinal PWM com preenchimento XX.
Em contraste, parar o mecanismo requer:
- configurações na saída 4 do sinal de qualquer valor,
- configurações no pino nº 5 do sinal PWM com um preenchimento de 0.
Cuidado! As direções específicas (frente / traseira) também dependem da maneira como os
fios são conectados aos motores – mais sobre isso mais adiante no artigo.
O primeiro teste de motores na prática
É hora do primeiro programa simples. Por enquanto, só verificaremos se os dois mecanismos estão funcionando corretamente. Tanto no eixo quanto no chassi da madeira compensada, os motores esquerdo (L – esquerdo) e direito (R – direito) são marcados.
Antes de prosseguir, certifique-se de que os fios do motor esquerdo (L no chassi)
estejam conectados ao soquete esquerdo do motor (L no eixo). Obviamente, o
motor direito (R) é análogo ao conector direito (R).
Vamos começar com a definição de pinos e suas configurações. Usaremos abreviações que permitirão identificar rapidamente os terminais:
- L (esquerda) – esquerda
- R (direita) – direita
- DIR (direção) – direção,
- PWM – pino, ao qual damos o sinal PWM ajustando a velocidade de um determinado motor.
Por exemplo, L_DIR significa o pino Arduino, que é usado para selecionar a direção de rotação do motor esquerdo.
#define L_PWM 5 #define L_DIR 4 #define R_PWM 6 #define R_DIR 9 void setup() { //Konfiguracja pinow od mostka H pinMode(L_DIR, OUTPUT); pinMode(R_DIR, OUTPUT); pinMode(L_PWM, OUTPUT); pinMode(R_PWM, OUTPUT); } void loop() { }
Agora é hora de ligar o motor esquerdo. Vamos começar com um simples ligar e desligar. O programa inteiro pode ser assim:
#define L_PWM 5 #define L_DIR 4 #define R_PWM 6 #define R_DIR 9 void setup() { //Konfiguracja pinow od mostka H pinMode(L_DIR, OUTPUT); pinMode(R_DIR, OUTPUT); pinMode(L_PWM, OUTPUT); pinMode(R_PWM, OUTPUT); } void loop() { //Obroty silnika przez sekundę do przodu z prędkością 100 digitalWrite(L_DIR, 0); //Ustawienie kierunku analogWrite(L_PWM, 100); //Ustawienie predkosci delay(1000); //Opoznienie 1 sekunda //Zatrzymanie silnika na sekundę digitalWrite(L_DIR, 0); //Ustawienie kierunku analogWrite(L_PWM, 0); //Wylaczenie silnika delay(1000); //Opoznienie 1 sekunda }
Por enquanto, durante os testes, use apenas PWM no intervalo de 0 a 100!
Um valor mais alto pode danificar motores – mais informações depois!
No programa acima, destaquei uma linha. É colocado lá excessivamente. Se o pino L_PWM estiver definido como 0, o estado L_DIR não fará diferença – o mecanismo será desligado.
O efeito deste programa é visível no vídeo:
Se o motor não girar – verifique se as fichas verdes estão montadas corretamente nos cabos do motor!
Dentro do conector deve estar apenas o pedaço do cabo exposto sem isolamento!
Antes de continuar, certifique-se de que o mesmo motor do lado esquerdo esteja funcionando no seu robots. Se este não for o caso, substitua as posições das fichas no eixo (direito com o motor esquerdo). Se o motor esquerdo estiver girando, mas na direção oposta, há duas opções:
- Você pode alterar a ordem dos fios na ficha do motor esquerdo.
- Não faça nada agora – “vamos melhorar” mais tarde programaticamente.
Independentemente do método escolhido, observe agora em qual lado o mecanismo esquerdo está girando quando o pino L_DIR é definido como 0. No meu caso, escrevo que o motor gira “para frente” e, mais corretamente – com essa rotação, o robot avança.
O teste é renovado para o segundo motor:
#define L_PWM 5 #define L_DIR 4 #define R_PWM 6 #define R_DIR 9 void setup() { //Konfiguracja pinow od mostka H pinMode(L_DIR, OUTPUT); pinMode(R_DIR, OUTPUT); pinMode(L_PWM, OUTPUT); pinMode(R_PWM, OUTPUT); } void loop() { digitalWrite(R_DIR, 0); //Ustawienie kierunku analogWrite(R_PWM, 100); //Ustawienie predkosci delay(1000); //Opoznienie 1 sekunda digitalWrite(R_DIR, 0); //Ustawienie kierunku analogWrite(R_PWM, 0); //Wylaczenie silnika delay(1000); //Opoznienie 1 sekunda }
Depois de iniciar este programa, o motor direito deve girar. Seria bom que a direção da rotação correspondesse ao motor esquerdo testado anteriormente. Se não for, então você tem duas opções:
- Troque a ordem dos fios na ficha do motor direito.
- Não faça nada agora – “vamos melhorar” mais tarde programaticamente.
Assim como antes, observe em que direção o mecanismo direito gira quando R_DIR é 0. No meu caso, será “para a frente”, que é o mesmo que no caso do motor esquerdo.
Por conveniência, seria bom ter uma situação em que, após dar 0
para pinos DIR, ambos os motores girarão na mesma direção.
Tarefa Adicional 4.1
Verifique como os motores se comportam para outros valores de PWM. Segure a faixa de 0 a 100. Assim, por exemplo, ver o que acontece quando a velocidade do conjunto “50”: analogWrite (R_PWM, 50); Verifique se os motores estão girando tão bem quanto para valores baixos de PWM, etc.
O próximo passo será o de escrever algumas características que permitem a fácil controle de motores. Mas antes de chegarmos a isso, vou explicar o que levou anteriormente limitar o PWM máximo a 100…
Limite de velocidade (tensão máxima segura)
Como se deve lembrar do curso dos fundamentos do Arduino ao usar o PWM, podemos ajustar o preenchimento de 0 a 255, onde 0 é 0% de preenchimento e 255 é 100% de preenchimento. Antes dos testes, inicialmente pedi para operar com um preenchimento de 0 a 100, o que resultou em um ajuste de 0% a cerca de 40% do preenchimento. De onde vem essa limitação?
O robot inteiro é alimentado por 6 pilhas AA, o que dá um máximo de 6 * 1,5V = 9V. Foi necessário para o funcionamento correto de toda a estrutura e esta é a voltagem que podemos fornecer aos motores – mas seria mortal para eles. As unidades usadas funcionam melhor quando são alimentadas com ~ 5V.
A maneira mais fácil de proteger os motores é
limitando o preenchimento máximo do sinal PWM.
Valor anteriormente imposto de 100 era apenas um exemplo, onde fez o estranho valor máximo 165 – porque essa é a maior realização que pode ser definida. Esse valor é cerca de 65% do preenchimento de PWM.
De onde veio esse valor? Foi escolhido experimentalmente em vez de motores, conectei um voltímetro ao robô e verifiquei a voltagem que aparece ali dependendo do PWM escolhido. Por 165 medi ligeiramente acima de 5V, o que será um valor seguro – especialmente que com o tempo as baterias estarão descarregando um pouco.
Vamos adicionar outra definição no topo do programa:
void stopMotors() { analogWrite(L_PWM, 0); //Wylaczenie silnika lewego analogWrite(R_PWM, 0); //Wylaczenie silnika prawego }
Programa pronto com funções
O programa básico que permitirá fácil diversão com o robot se parece com isso:
#define L_PWM 5 #define L_DIR 4 #define R_PWM 6 #define R_DIR 9 #define PWM_MAX 165 void setup() { //Konfiguracja pinow od mostka H pinMode(L_DIR, OUTPUT); pinMode(R_DIR, OUTPUT); pinMode(L_PWM, OUTPUT); pinMode(R_PWM, OUTPUT); } void loop() { } void leftMotor(int V) { if (V > 0) { //Jesli predkosc jest wieksza od 0 (dodatnia) V = map(V, 0, 100, 0, PWM_MAX); digitalWrite(L_DIR, 0); //Kierunek: do przodu analogWrite(L_PWM, V); //Ustawienie predkosci } else { V = abs(V); //Funkcja abs() zwroci wartosc V bez znaku V = map(V, 0, 100, 0, PWM_MAX); digitalWrite(L_DIR, 1); //Kierunek: do tyłu analogWrite(L_PWM, V); //Ustawienie predkosci } } void rightMotor(int V) { if (V > 0) { //Jesli predkosc jest wieksza od 0 (dodatnia) V = map(V, 0, 100, 0, PWM_MAX); digitalWrite(R_DIR, 0); //Kierunek: do przodu analogWrite(R_PWM, V); //Ustawienie predkosci } else { V = abs(V); //Funkcja abs() zwroci wartosc V bez znaku V = map(V, 0, 100, 0, PWM_MAX); digitalWrite(R_DIR, 1); //Kierunek: do tyłu analogWrite(R_PWM, V); //Ustawienie predkosci } } void stopMotors() { analogWrite(L_PWM, 0); //Wylaczenie silnika lewego analogWrite(R_PWM, 0); //Wylaczenie silnika prawego }
Movimentos possíveis do robot
Agora vale a pena considerar os movimentos que um robot pode fazer. Nós temos uma unidade aqui, que consiste em dois motores controlados independentemente. Sem volantes, por isso não podemos falar sobre a direção aqui como num carro.
Voltas e voltas serão possíveis para controlar a
velocidade e as direções de rotação de motores individuais.
Dirigindo de um lado para outro
A primeira possibilidade básica de um robot é dirigir para frente ou para trás. Aqui o assunto é bastante óbvio. Se as duas rodas estiverem girando na mesma direção e na mesma velocidade, o robot irá na direção. Há algumas exceções a isso, mas mais sobre isso depois…
Para obter esse efeito, os seguintes comandos devem ser emitidos. Por dirigir para frente:
Rotação em relação ao círculo
Se o robot estiver girando apenas uma das rodas, a nossa construção será feita num pequeno arco. Especificamente, ele irá girar em torno desta unidade estacionária.
Para executar tais manobras, os seguintes comandos devem ser emitidos. Para rotação em relação à roda esquerda:
rightMotor(60); //Prawy do przodu z 60% predkosci leftMotor(0); //Lewy wyłączony
Para rotação em relação à unidade certa:
rightMotor(0); //Prawy wyłączony leftMotor(60); //Lewy do przodu z 60% predkosci
No entanto, esse método de fazer turnovers é
usado muito raramente.
Turnovers no local
Uma das possibilidades mais interessantes é o turnover realizado literalmente no lugar. Nosso robot também será capaz de fazer isso. É o suficiente para as rodas girarem em direções opostas:
Para executar tais manobras, os seguintes comandos devem ser emitidos. Para turnover à esquerda:
rightMotor(60); //Prawy do przodu z 60% predkosci leftMotor(-60); //Lewy do tyłu z 60% predkosci
Para o turno certo:
rightMotor(-60); //Prawy do tyłu z 60% predkosci leftMotor(60); //Lewy do przodu z 60% predkosci
Claro, outras opções também são possíveis. Ao controlar os motores em velocidades diferentes, poderemos navegar pelas curvas, etc. Encorajo-o a verificar os métodos descritos acima na prática. Deixe-me saber nos comentários se tem algum efeito interessante! Todos os materiais de vídeo são especialmente bem vindos!
Testes de possíveis movimentos na prática
Agora pode escrever programas que irão verificar como o robot lida com o passeio. A realização do percurso de amostra é como se segue:
#define L_PWM 5 #define L_DIR 4 #define R_PWM 6 #define R_DIR 9 #define PWM_MAX 165 void setup() { //Konfiguracja pinow od mostka H pinMode(L_DIR, OUTPUT); pinMode(R_DIR, OUTPUT); pinMode(L_PWM, OUTPUT); pinMode(R_PWM, OUTPUT); } void loop() { leftMotor(60); //Jazda do przodu z predkoscią 60% rightMotor(60); delay(1000); //Jazda przez sekunde leftMotor(-50); //Obrot w miejscu z predkoscią 50% rightMotor(50); delay(2000); //Czas trwania obrotu 2 sekundy leftMotor(-80); //Jazda do tyłu z predkoscią 80% rightMotor(-80); delay(1000); //Jazda do tyłu przez sekunde } void leftMotor(int V) { if (V > 0) { //Jesli predkosc jest wieksza od 0 (dodatnia) V = map(V, 0, 100, 0, PWM_MAX); digitalWrite(L_DIR, 0); //Kierunek: do przodu analogWrite(L_PWM, V); //Ustawienie predkosci } else { V = abs(V); //Funkcja abs() zwroci wartosc V bez znaku V = map(V, 0, 100, 0, PWM_MAX); digitalWrite(L_DIR, 1); //Kierunek: do tyłu analogWrite(L_PWM, V); //Ustawienie predkosci } } void rightMotor(int V) { if (V > 0) { //Jesli predkosc jest wieksza od 0 (dodatnia) V = map(V, 0, 100, 0, PWM_MAX); digitalWrite(R_DIR, 0); //Kierunek: do przodu analogWrite(R_PWM, V); //Ustawienie predkosci } else { V = abs(V); //Funkcja abs() zwroci wartosc V bez znaku V = map(V, 0, 100, 0, PWM_MAX); digitalWrite(R_DIR, 1); //Kierunek: do tyłu analogWrite(R_PWM, V); //Ustawienie predkosci } } void stopMotors() { analogWrite(L_PWM, 0); //Wylaczenie silnika lewego analogWrite(R_PWM, 0); //Wylaczenie silnika prawego }
Abaixo pode ver as tentativas com outros programas e configurações, eu encorajo toda a gente a fazer estes testes:
Por que o robot “não pode” ir direto?
Muitos iniciantes são muito triste quando o comando “para a frente” vê que o robot não se comporta como esperado.
Isso resultará num passeio de curva. Infelizmente, será, mas não é uma coisa má. Existem muitas razões. Lembre-se que os motores, engrenagens e rodas são elementos mecânicos… Nada é perfeito. Um motor será sempre um pouco mais rápido, uma transmissão colocará um pouco mais de resistência.
A soma de tais erros fará com que o robot sempre se transforme em um lado. Dirigir em linha reta é uma tarefa bastante complicada. As construções que precisam seguir em frente são equipadas com unidades mais caras, e sensores que realmente medem a velocidade do motor são frequentemente adicionados. O uso de programas mais avançados permite que você siga em frente.
“Curva” não é um problema de todo!
Dirigir em linha reta é necessário em algumas situações. Agora estamos testando o comportamento do robot com operações rigidamente programadas, de modo que a condução no arco será visível.
No entanto, em última análise, queremos construir um robot real, ou seja, um sistema que, além das
unidades, tenha sensores que sejam “olhos” do nosso veículo!
Na próxima parte do curso, adicionaremos sensores mecânicos de obstáculos que protegerão o robot contra colisão com a parede. Em vez de dirigir cegamente em direção a um obstáculo, ele poderá reagir ao ambiente e alterar a velocidade dos motores.
Se a diferença nas revoluções do motor for relativamente grande ou incomodar muito alguém, você poderá tentar corrigir o erro no programa. Apenas reduza alguns PWM_MAX para um mecanismo mais rápido. No entanto, esta solução pode revelar-se fatal. Eu os recomendo apenas na forma de testes. Durante as outras partes do curso, não precisa se preocupar com isso.
Tarefa adicional 4.2
Escreva um programa que segue a seguinte rota:
Tarefa Adicional 4.3
Escreva um programa que execute a tarefa de aumentar e diminuir suavemente a velocidade:
Sumário
Nesta parte do curso, revivemos o nosso veículo, que agora pode navegar pelas rotas programadas. Como parte do exercício, recomendo que escreva alguns programas, graças aos quais o robot poderá superar trajetórias imaginadas por os nossos leitores, como dirigir um retângulo, uma elipse, girar etc.
No próximo artigo, trataremos de sensores mecânicos de obstáculos, que permitirão a primeira condução autónoma do nosso veículo. Desta vez ele será capaz de evitar obstáculos sozinho!