Beruflich Dokumente
Kultur Dokumente
Sistemas Mecatrnicos
Proponente:
Agosto de 2015
Resumo
O presente trabalho apresenta a leitura, analise e descrio de trs diferentes relatrios
de trs grupos de alunos que, ao longo da disciplina de Sistemas Mecatrnicos,
desenvolveram um projeto, desde a concepo at a construo, de sistemas robticos
utilizando a plataforma de prototipagem eletrnica conhecida como Arduino. Ser explicado
com detralhes a programao utilizada nos referidos relatrios.
1. Introduo
Arduino uma plataforma de prototipagem eletrnica, criada por Massimo Banzi e David
Cuartielles em 2005 com objetivo de permitir o desenvolvimento de controle de sistemas
interativos, de baixo custo e acessvel a todos.
O projeto foi criado pensando em artistas e amadores, ou seja, no necessrio ter
conhecimentos prvios em eletrnica ou programao para iniciar-se no mundo Arduino.
Com o Arduino possvel tambm enviar e receber informaes de praticamente qualquer outro
sistema eletrnico. Desta forma possvel contruir por exemplo, um sistema de captao de
dados de sensores, como temperatura, iluminao, processar e enviar esses dados para um
sistema remoto por exemplo. Outra caracterstica importante que todo material (software,
bibliotecas, hardware) open-source, ou seja, pode ser reproduzido e usado por todos sem a
necessidade de pagamento de royalties ou direitos autorais.
A plataforma composta essencialmente de duas partes: O Hardware e o Software.
Arduino uno
Resumidamente o hardware uma placa eletrnica que possui todos componentes necessrios
para a maioria dos projetos e contm uma eletrnica que permite usar a placa com diversas
fontes de energia, baterias e fontes de alimentao. O hardware tambm permite o acoplamento
de circuitos externos atravs de pinos de conexo em posies padronizadas.
J com relao ao software, o Arduino um compilador gcc (C e C++) baseado em Wiring e
que usa uma interface grfica contruda em Java baseado no projeto Processing. Tudo isso
resume-se a um programa IDE (ambiente de desenvolvimento integrado) muito simples de usar e
de estender com bibliotecas que podem ser facilmente encontradas na internet.
2. Objetivos
3. Desenvolvimento
O desenvolvimento ser apresentado mostrando-se os trechos da programao de cada grupo
com a explicao logo abaixo.
3.1. Grupo Guilherme Leal/Pablo/Veiga/Isabella (carro)
#include <waypointClass.h>
#include <TinyGPS.h> // biblioteca para gps
#include <Wire.h>
#include "DualVNH5019MotorShield.h"
#include <TinyGPS.h>
#define HMC5883_WriteAddress 0x1E // i.e 0x3C >> 1
#define HMC5883_ModeRegisterAddress 0x02
#define HMC5883_ContinuousModeCommand 0x00
Essa parte responsvel pelo cdigo de bssola.
#define HMC5883_DataOutputXMSBAddress 0x03
TinyGPS gps;
// Waypoints
#define WAYPOINT_DIST_TOLERANE 5
#define NUMBER_WAYPOINTS 3
int waypointNumber = 0;
waypointClass
waypointList[NUMBER_WAYPOINTS]
{waypointClass(-47.878017,-
originalDistanceToTarget;
int distanceToWaypoint(void) ;
float angle;
float erro;
5
Serial1.begin(38400);
Serial.begin(9600);
Serial.print("Lets
start
the
show!
Run,
Barry
Run
!");
//Serial.println(TinyGPS::library_version());
Serial.println();
Wire.begin();
Inicia a biblioteca Wire para fazer parte da I2C bus (faz parte da bssola).
A funo void setup() funciona como uma funo de inicializao, o que estar contido nela
rodar apenas uma vez no programa.
Na comunicao serial, possvel obter todos os dados que o Arduino est gerando ou
recebendo e enviar ao computador para simplesmente analisar os dados ou rodar algum outro
programa.
Iniciou-se a comunicao serial com a funo "Serial.begin(taxa); cada dispositivo
configurado para receber uma taxa de bits especfica (9600 a taxa do computador) a funo
"Serial.print" Envia dados para a porta serial como texto legvel ASII.
void loop() {
Os procedimentos colocados nessa funo so realizados mais de uma vez em forma de
looping.
int sE=digitalRead(31);
int sD=digitalRead(37);
So declaradas as variveis sE e sD (sensores ticos). DigitalRead um cdigo para configurar
portas digitais como entrada, no caso as portas 31 e 37, portanto o que for lido nas portas 31 e 37
ser considerado como sE e sD respectivamente.
if((sE == 0) && (sD == 0)){
int i = 45;
int j = 35 ;
7
md.setM1Speed(i);
md.setM2Speed(j);
stopIfFault();
}
else if((sE == 1) && (sD == 0)){
int i = -45;
int j = 45 ;
md.setM1Speed(i);
md.setM2Speed(j);
stopIfFault();
}
else if((sE == 0) && (sD == 1)){
int i = 45;
int j = -45 ;
md.setM1Speed(i);
md.setM2Speed(j);
stopIfFault();
}
else if((sE ==1) && (sD == 1)){
int i=0;
md.setM1Speed(i);
md.setM2Speed(i);
stopIfFault();
k=1;
}
Todo o fragmento anterior em que foi usada a estrutura condicional if e else quer dizer que
dependendo do valor de sE e sD as variveis i e j sero os valores declarados em int e portanto
ser executado cdigo md.setM1Speed(i) e md.setM2Speed(j) e ao final de cada condio, h a
8
funo stopIfFault() para haver o controle de possveis erros. Todo esse fragmento representa a
programao do seguidor de linhas ( sE o sensor tico da eireita e sD o da direita) cada
condio mostrada a condio imposta para o funcionamento dos motores. por exemplo na
condio 1 que o primeiro if. Se ambos os sensores mostrarem valor binrio zero ( o que
significa que os sensores no esto captando nenhuma linha) as velodidades dos motores
( md.setM1Speed()) so ditadas pelas veriveis i e j, no caso 45 e35.
while (k==1){
A varivel k foi definida anteriormente como sendo zero, esse while coloca uma condio
quando o k fica com valor 1 , inicia-se a bussola.
int i,x,y,z;
Declaradas as variveis
double angle;
A varivel double assim como float tambm utilizada para valores de ponto flutuante, no
caso o ngulo.
Wire.beginTransmission(HMC5883_WriteAddress);
Wire.write(regb);
Wire.write(regbdata);
Wire.endTransmission();
// delay(100);
Wire.beginTransmission(HMC5883_WriteAddress); //Initiate a transmission with HMC5883
(Write address).
Wire.write(HMC5883_ModeRegisterAddress);
buffer.
Wire.write(HMC5883_ContinuousModeCommand);
transmission.
//delay(100);
9
specified.
// delay(100);
for(i=0;i<6;i++)
{
outputData[i]=Wire.read(); //Store the data in outputData buffer
}
}
x=outputData[0] << 8 | outputData[1]; //Combine MSB and LSB of X Data output register
z=outputData[2] << 8 | outputData[3]; //Combine MSB and LSB of Z Data output register
y=outputData[4] << 8 | outputData[5]; //Combine MSB and LSB of Y Data output register
/* Serial.print(" y ");
Serial.println(y);
Serial.print(" x ");
Serial.println(x);
Serial.print("z ");
Serial.println(z);*/
y = (double)y;
x=(double)x;
z=atan2((double)y,(double)x);
10
Quando nenhum dado encontrado a funo Serial.printIn mostra na tela o aviso "** No
characters received from GPS: check wiring **".
targetLat = waypointList[waypointNumber].getLat();
targetLong = waypointList[waypointNumber].getLong();
Serial.print("Latitude Atual: ");
Serial.print(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat, 6);
Serial.print (" Latitude do Waypoint: ");
Serial.println (targetLat,6);
Serial.print(" Longitude Atual: ");
Serial.print(flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon, 6);
Serial.print (" Longitude do Waypoint: ");
Serial.println (targetLong,6);
Serial.print (" Angulo Atual: ");
Serial.println(angle);
Serial.print(" Angulo Alvo: ");
Serial.println(targetHeading);
Caso o GPS receba algum dado, ele envia para o serial monitor os valores da latitude e
longitude e armazena esses dados.
Abaixo comea o sistema de navegao:
targetHeading=courseToWaypoint();
float erro=targetHeading-angle;
distanceToWaypoint() ;
if (erro < -180)
erro += 360;
if (erro > 180)
erro -= 360;
Serial.print (" Erro: ");
Serial.println (erro);
12
targetLong = waypointList[waypointNumber].getLong();
if (waypointNumber >= NUMBER_WAYPOINTS)
{
md.setM1Speed(0);
md.setM2Speed(0);
stopIfFault();
while (1);
}
distanceToTarget = originalDistanceToTarget = distanceToWaypoint();
int distanceToWaypoint()
{
float delta = radians(flon );
float sdlong = sin(delta);
float cdlong = cos(delta);
float lat1 = radians(flat);
float lat2 = radians(targetLat);
float slat1 = sin(lat1);
float clat1 = cos(lat1);
float slat2 = sin(lat2);
float clat2 = cos(lat2);
delta = (clat1 * slat2) - (slat1 * clat2 * cdlong);
delta = sq(delta);
delta += sq(clat2 * sdlong);
delta = sqrt(delta);
float denom = (slat1 * slat2) + (clat1 * clat2 * cdlong);
delta = atan2(delta, denom);
distanceToTarget = delta * 6372795;
if (abs(distanceToTarget )<= WAYPOINT_DIST_TOLERANE)
nextWaypoint();
Serial.print ("Distancia : ");
Serial.println (distanceToTarget);
return distanceToTarget;
14
}
int courseToWaypoint()
{
float dlon = radians(targetLong-flon);
float cLat = radians(flat);
float tLat = radians(targetLat);
float a1 = sin(dlon) * cos(tLat);
float a2 = sin(cLat) * cos(tLat) * cos(dlon);
a2 = cos(cLat) * sin(tLat) - a2;
a2 = atan2(a1, a2);
if (a2 < 0.0)
{
a2 += TWO_PI;
}
targetHeading = degrees(a2);
return targetHeading;
}
Por fim, nesse ltimo fragmento de programao, definido como o rob vai atingir os
pontos desejados. So utilizadas formulas de geometrias para serem obtidas as distncias.
3.2. Grupo Marcos Brasil/Evandro/Rafael (rob Scara)
// interface serial: enviar 3 valores
// (posicao1,posicao2,posicao3) (motor1, motor2, servo)
#include <Encoder.h> //BIBLIOTECA DO ENCODER
#include <Servo.h> //BIBLIOTECA DO SERVO
#include <math.h>
#define MAX 3
#define MIN(A,B) (((A)<(B))?(A):(B))
#define MAXI(A,B) (((A)>(B))?(A):(B))
Foram definidas as bibliotecas.
Servo myservo;
int IN1 = 44; // motor 1
int IN2 = 34; // motor 1
int IN3 = 35; // motor 2
int IN4 = 45; // motor 2
15
16
esto sendo enviadas ou recebidas a partir de um dispositivo externo. O tamanho do buffer seria
de 10 bytes neste caso.
char caracter;
long posicao1;
long posicao2;
float posicaoq21;
float posicaoq22;
float posicaoq11;
float posicaoq12;
Variaveis declaradas sem um valor prvio com relao s posies dos motores e do braos
segundo a cinemtica.
long val;
float a1;
float a2;
Varivel para o comprimento dos braos do robo a1 e a2
bool dadoPronto = false;
Varivel booleana aceita apenas dois valores: verdadeiro e falso. Cada varivel booleana
ocupa 1 bit de memria.
int dadosRecebidos = 0;
float valoresRecebidos[MAX];
int posicaoRecebidos = 0;
Encoder Enc1(canal1, canal2);
Encoder Enc2(canal3, canal4);
Foram definidos os canais do encoder dos motores. A biblioteca Encoder monitora os 2 pinos e
atualiza uma contagem da mudana relativa na posio. A biblioteca atualiza sua contagem em
cada mudana que muitas vezes chamado de 4X contando, desde 4 contagens esto disponveis
para cada marca fsica ou buraco no hardware.
const float reducao = 17.442;
// Pulsos/ da saida
const float Kp1 = .3; //constante proporcional1
const float Kp2 = .2; //constante proporcional2
long a;
Segundo o relatrio: Como o rob possui uma inrcia e velocidade, ao chegar no valor este
acaba passando do ponto desejado, fazendo com que o erro mude o sinal e fazendo com que o
motor gire no sentido oposto, fazendo novamente que o brao passe do ponto desejado, repetindo
o ciclo. Para solucionar este problema foi criada uma constante Kp que ser multiplicada pelo
erro
void setup() {
17
A funo "setup ()" acionada quando um esboo comea. usada para inicializar variveis ,
modos de pino , comear a usar as bibliotecas , etc.
O procedimento ser executado apenas uma vez, aps cada inicializao ou reset do Arduino.
O "void" significa nada, ou seja, este procedimento no retorna nada. Isso no significa que ele
no faz nada, apenas que ele no tem um nmero tangvel ou qualquer outra coisa , para mostrar
quando o procedimento se completa).
pinMode(sensor1, INPUT_PULLUP);
pinMode(sensor2, INPUT_PULLUP);
Usa-se a afirmao "pinMode" para definir se um pino ser fisicamente usado como uma
sada ou como uma entrada. No caso, os pinos dos sensores 1 e 2 so usados como entradas e
ainda em PULLUP que significa que na montagem h um resistor entre o sensor e a alimentao
de 5V.
Serial.begin(115200);
Esse procedimento inicia uma comunicao serial. A comunicao serial (UART) na
plataforma Arduino um recurso que possibilita a comunicao entre a placa e um computador
ou entre a placa e outro dispositivo. atravs desse canal que realizado o upload do cdigo
para a placa. Nesse caso a comunicao se d uma taxa de 115200 bits.
a1 = 80;
a2 = 145;
Foram definidos os comprimentos dos braos do rob.
myservo.attach(46);
Anexar a varivel cervo a um pino, no caso o 46.
bufferIndex = 0;
Quantidade de espao de memria utilizado inicialmente.
pinMode(34, OUTPUT);
pinMode(44, OUTPUT);
pinMode(35, OUTPUT);
pinMode(45, OUTPUT);
start ();
}
Utilizao do pinMode para definir os pinos dos motores como sadas. O procedimento "start"
est chamando uma sub rotina explicitada em void mais a frente.
void loop() {
lePortaSerial();
O comando acima est chamando uma sub rotina que declarada e explicitada em void mais a
frente.
18
val = valoresRecebidos[2];
1023)
analogWrite(ENA, (V1));
}
O procedimento condicional serve nesse caso para, dependendo do valor do erro, enviar
comandos para o motor e gir-lo na direo certa e com a velocidade certa.
O procedimento digitalWrite envia informao para a entrada digital (pino chamado de INx
nesse programa em especfico), no caso do motor fazendo-o funcionar ou no com o HIGH e
LOW.
O procedimento analogWrite faz a mesma coisa que o digital mas para a sada ENA e
aplicando a velocidade V1 no motor.
//atualiza motor 2
posicao2 = Enc2.read();
erro2 = (posicaoq22 * reducao * 4) - posicao2 - 69;
V2 = MIN(200, abs(erro2) * Kp2);
V2 = MAXI(48, V2);
if ( erro2 > 0 ) {
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
analogWrite(ENB, abs(V2));
}
if (erro2 < 0) {
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
analogWrite(ENB, abs(V2));
}
//if(erro2 == 0){ //teoricamente no precisa
// digitalWrite(IN3,LOW);
//digitalWrite(IN4,LOW);
//}
A mesma coisa do motor 1 realizada para o motor 2.
if (dadoPronto) {
Serial.print("Dados recebidos: ");
Serial.println(dadosRecebidos);
}
Se houverem dados prontos disponveis so plotados na tela os dados recebidos.
dadoPronto = false;
dadosRecebidos = 0;
//retorna posio atual e erro
Serial.print(digitalRead(sensor1));
Serial.print(",");
Serial.print(posicao1);
Serial.print(",");
Serial.print(erro1);
Serial.print(",");
Serial.print(posicao2);
20
Serial.print(",");
Serial.print(erro2);
Serial.print(",");
Serial.print(V1);
Serial.print(",");
Serial.println(V2);
}
A funo serial print serve para tornar os dados em dados legveis na tela do computador.
void lePortaSerial() {
while (Serial.available() > 0) {
caracter = Serial.read();
Essa sub-rotina define que quando h disponveis valores seriais, esses valores lidos so
armazenados como a varivel caracter.
if (((caracter >= '0') && (caracter <= '9')) || (caracter == '-')) {
buffer[bufferIndex] = caracter;
bufferIndex++;
}
else
{
if ((caracter == ',') && (buffer > 0) && (posicaoRecebidos < MAX)) {
buffer[bufferIndex] = 0;
valoresRecebidos[posicaoRecebidos] = atoi(buffer);
posicaoRecebidos++;
bufferIndex = 0;
}
if (caracter == '\n') {
if ((buffer > 0) && (posicaoRecebidos < MAX)) {
buffer[bufferIndex] = 0;
valoresRecebidos[posicaoRecebidos] = atoi(buffer);
}
bufferIndex = 0;
dadosRecebidos = posicaoRecebidos + 1;
posicaoRecebidos = 0;
Serial.println("----");
for (int i = 0; i < MAX; i++) {
Serial.print("valor[");
Serial.print(i);
Serial.print("] = ");
Serial.println(valoresRecebidos[i]);
}
dadoPronto = true;
}
}
}
}
21
Enc2.write(-9100);
erro2 = 0;
}
}
A mesma coisa acontece com o sensor e eixo 2
valoresRecebidos[0] = 225;
valoresRecebidos[1] = 0;
valoresRecebidos[2] = 100;
Serial.println("--------------------------------");
Serial.println("-------Origem Reconhecida-------");
Serial.println("-333333333333333333333333333333-");
delay(500);
Serial.println("-222222222222222222222222222222-");
delay(500);
Serial.println("-111111111111111111111111111111-");
delay(500);
}
Ao final do posicionamento o programa avisa que a origem conhecida e pode-se continuar
O MAC ( Media Access Control ) o endereo de hardware de seu escudo de ethernet para o
dispositivo (array de 6 bytes).
IPAddress ip(192, 168, 1, 3); // IP address, may need to change depending on network
EthernetServer server(80); // create a server at port 80
So declaradas as duas constantes anteriores cujo significado j foi explicaod em comentrio.
String HTTP_req; // stores the HTTP request
char angulo0[3], angulo1[3], angulo2[3], caracter;
int i = 0, j = 0, k = 0;
boolean pega0 = 0, pega1 = 0, pega2 = 0;
Definem-se algumas variveis e seus valores.
#define IN1 6 // -> Porta onde vai o fio amarelo (que vem da ponte H) do motor 1
#define IN2 7 // -> Porta onde vai o fio laranja (que vem da ponte H) do motor 1
#define ENA 5 // -> Porta onde vai o fio verde (que vem da ponte H) do motor 1
#define IN3 8 // -> Porta onde vai o fio amarelo (que vem da ponte H) do motor 2
#define IN4 9 // -> Porta onde vai o fio laranja (que vem da ponte H) do motor 2
#define ENB 4 // -> Porta onde vai o fio verde (que vem da ponte H) do motor 2
Foi utilizada uma ponte H, muito utilizada para controle de direo e velocidade de giro de
motores eltricos. Foram definidas cada uma portas referentes ao motor.
#define SER 44 // -> Porta onde vai o servo
#define FDC 20 // -> Porta onde vai o sensor de fim de curso
#define SOT 21 // -> Porta onde vai o sensor tico
#define Batente 180 // -> Limite para a posio do motor 1 []
#define Batente2 90 // -> Limite para a posio do motor 2 []
Encoder Enc1(19,18); // -> Portas onde vo os fios branco e verde do Encoder 1
Encoder Enc2(3,2); // -> Portas onde vo os fios branco e verde do Encoder 2
24
Assim como o grupo "Marcos", tambm foi usado motores com encoders acoplados.
double LimDir = 0, LimEsq = 0, Zero = 0;
Definidas variveis de limite.
Servo servo;
Chamada para a varivel servo da biblioteca.
#define interval 500 // -> Intervalo para o print das informaes [ms]
long previousMillis = 0; // -> Varivel auxiliar para definir o instante do print
#define LIM1 200 // -> Limite do Output do motor 1 [0,255]
#define LIM2 200 // -> Limite do Output do motor 2 [0,255]
#define MAX 3 // -> Nmero de dados recebidos pelo Serial
Os trs ltimos define referem-se velocidade dos motores.
//int valoresRecebidos[MAX];
int ang0 = 0, ang1 = 0, ang2 = 0;
double Setpoint1 = 0, Input1, Output1 = 0;
double Setpoint2 = 0, Input2, Output2 = 0;
#define MIN 1
#define Kp1 4.5 // -> Ganho proporcional
#define Ki1 0.6 // -> Ganho integral
#define Kd1 0.5 // -> Ganho derivativo
#define Kp2 5 // -> Ganho proporcional
#define Ki2 0.4 // -> Ganho integral
#define Kd2 0.35 // -> Ganho derivativo
PID PID1(&Input1, &Output1, &Setpoint1, Kp1, Ki1, Kd1, DIRECT);
PID PID2(&Input2, &Output2, &Setpoint2, Kp2, Ki2, Kd2, DIRECT);
25
Segundo o relatrio do grupo, A leitura dos encoders pode ser variada com um valor inicial
desejado, ou seja, um setpoint inicial, ou por alterao por uma influncia externa. Um valor de
Output lido dos encoders por meio de uma rotina presente na biblioteca. Assim como o grupo
citado anteriormente, a atuao do encoder facilita o controle proporcional pois cria parmetros
que podem ser comparados com os parmetros dos setpoints e assim encontram-se os erros e
pode-se fazer o controle. Novamente esse erro no zero o que gera a necessidade do controle
PID e assim a utilizao da biblioteca PID para obteno dos ganhos. Esses ganhos foram
definidos acima assim como a chamada para o controle PID.
void setup() {
Ethernet.begin(mac, ip); // initialize Ethernet device
server.begin();
26
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(ENA, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
pinMode(ENB, OUTPUT);
Define os pinos relativos aos motores como sadas, pois esses pinos enviam informao aos
motores.
pinMode(FDC, INPUT);
pinMode(SOT, INPUT);
Define-se os pinos dos dois sensores como entrada, pois recebe-se a informao vinda dos
sensores.
Serial.println("------- Setup -------");
Regulagem para posicionamento e leitura desse posicionamento dos braos. (Setup).
if(digitalRead(SOT) == 1) {
Se a entrada digital acusar valor 1 significa que o brao est sendo captado pelo sensor.
Serial.println("Mova o braco longe do sensor otico");
while(digitalRead(SOT) == 1) {
delay(50);
escrito na tela do computador para mover o brao para longe do sensor enquanto o seu calor
for 1 ou seja, estiver captando o brao.
}
}
Serial.println("Mova o braco ate o sensor otico");
while(digitalRead(SOT) == 0) {
27
delay(50);
}
Enc1.write(0);
Serial.println("Encoste o braco no sensor da direita");
// Comeo da rotina da calibrao
while(digitalRead(FDC) == 1) {
LimDir = Enc2.read();
H um comando para o operador encostar o brao do rob no sensor da direita com isso a
entrada digital acusa 1 e assim pode-se registrar o valor lido pelo encoder na varivel LimDir
}
Serial.println(LimDir);
delay(500);
while(digitalRead(FDC) == 0) {
Quando o valor acusado 1, pode-se voltar o brao para o meio para iniciar a calibrao para
o outro lado.
Serial.println("Volte para o meio");
delay(500);
}
Serial.println("Encoste o brao no sensor da esquerda");
while(digitalRead(FDC) == 1) {
LimEsq = Enc2.read();
//NOvamente registrado o valor de distncia para uma varivel, no caso LimEsq, lido pelo
encoder.
}
Enc2.write((LimEsq-LimDir)/2);
Serial.println(LimEsq);
28
LimDir = ((abs(LimDir-LimEsq)/2)*360)/(334*75.0);
LimEsq = -LimDir;
Serial.println(LimDir);
Serial.println(LimEsq); // -> Fim da rotina de calibrao
Serial.setTimeout(10); // -> Tempo que a funo Serial.parseInt() leva para adquirir os dados
[ms]
PID1.SetOutputLimits(-LIM1, LIM1);
PID1.SetMode(AUTOMATIC);
PID2.SetOutputLimits(-LIM2, LIM2);
PID2.SetMode(AUTOMATIC);
Serial.println("------- Loop -------");
}
Ao final disso o rob est calibrado com as distncia permitidas para o movimento
registradas.
void loop() {
Rede();
lePortaSerial();
As duas chamadas acima so para subrotinas explicitadas mais abaixo no programa.
Input1 = ((Enc1.read()*360)/(334*75.0));
Setpoint1 = ang0;
Input2 = ((Enc2.read()*360)/(334*75.0));
Setpoint2 = ang1;
PID1.Compute();
PID2.Compute();
if(digitalRead(FDC) == LOW) {
Output2 = 0;
}
if(Output1 < 0) {
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
29
analogWrite(ENA, abs(Output1));
Estabeleceu-se que para um valor negativo do Erro, o motor rotaciona com potncia mxima
(ENA) em um sentido.
}
else {
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
analogWrite(ENA, abs(Output1));
}
if(Output2 < 0) {
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
analogWrite(ENB, abs(Output2));
}
//De forma anloga, um valor positivo no Erro resulta no motor rotacionando com potncia
mxima no sentido oposto.
else {
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
analogWrite(ENB, abs(Output2));
}
servo.write(ang2+90);
unsigned long currentMillis = millis();
if(currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
Serial.print("Posicoes: ");
Serial.print(Input1);
Serial.print(" deg, ");
Serial.print(Input2);
Serial.print(" deg, ");
30
Serial.print("Pedidos: ");
Serial.print(Setpoint1);
Serial.print(" deg, ");
Serial.print(Setpoint2);
Serial.print(" deg, ");
Serial.print(ang2);
Serial.print(" deg, ");
Serial.print("Fim de curso: ");
Serial.print(digitalRead(FDC));
Serial.print(", ");
Serial.print("Torques: ");
Serial.print(Output1);
Serial.print(", ");
Serial.println(Output2);
}
}
Assim como no grupo anterior, o loop serve para controle do motor e dos servos. Utilizandose dos imputs e outputs gerados pelo controle PID pode-se dar os comandos necessrios aos
controladores, e assim mover o robo e ainda ao final registrar com o Serial.print todos os
parmetros que demonstram o estado do robo como angulos, velocidades, posies etc.
void lePortaSerial() {
Encontrar os ngulos respectivos no link URL recebido do browser, e trabalhar os dados para
que sirvam de entrada para o controle PID, que d o sinal para os atuadores.
while (Serial.available() > 0) {
if(pega0){
ang0 = Serial.parseInt();
Serial.print("Junta 1: ");
Serial.println(ang0);
pega0 = 0;
}
31
if(pega1){
ang1 = Serial.parseInt();
Serial.print("Junta 2: ");
Serial.println(ang1);
pega1 = 0;
}
if(pega2){
ang2 = Serial.parseInt();
Serial.print("Junta 3: ");
Serial.println(ang2);
pega2 = 0;
}
caracter = Serial.read();
if ((caracter == 'b') && (i==0)){
i++;
}
else if ((caracter == 'a') && (i==1))
i++;
else if ((caracter == 's') && (i==2))
i++;
else if ((caracter == 'e') && (i==3))
i++;
else if ((caracter == '=') &&(i==4)){
i++;
pega0 = 1;
i = 0;
}
if ((caracter == 'i') && (j==0)){
j++;
}
else if ((caracter == 'n') && (j==1))
j++;
else if ((caracter == 'k') && (j==2))
j++;
32
33
4. Referncias Bibliogrficas
http://www.ladyada.net/learn/arduino/
https://www.arduino.cc/
34