• Welcome to LusoRobótica - Robótica em Português.
 

projecto linefollowing+arduino

Started by rafasta, 04 de April de 2012, 16:55

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

rafasta

boas este é o meu primeiro projecto e decidi fazer um robo de line following. para isso decidi utilizar o arduino e um ssensor da polulo qtr-8rc. com a biblioteca consegui obter valores e seguir uma linha mas foi em semi-circulos. apos uma pesquisa aqui no forum e na net percebi que tinha de utilizar algo chamado PID mas nao sei como implementa-lo no meu codigo nem exactamente o que é (este é o meu primeiro projecto e nao percebo muito ainda de progamação). sera que alguem me pode ajudar?

senso

Basicamente o que tu queres é que o robot mantenha sempre a linha no centro dos sensores, e para isso o que pode fazer é variar a velocidade de cada motor de modo a descrever curvas.
O que o PID te oferece é um método de controlo em malha fechada, em que defines os ganhos do sistema de controlo de modo a ter a melhor resposta possivel.
Tens uma biblioteca para Arduino bastante boa até:
http://arduino.cc/playground/Code/PIDLibrary

E aconselho leres isto:
http://brettbeauregard.com/blog/2011/04/improving-the-beginners-pid-introduction/

O teu setPoint será o valor que o sensor retorna quando a linha está no centro dos sensores, e o output será a velocidade dos motores entre 0-255 para aplicar directamente via pwm nos motores.
Avr fanboy

rafasta

Obrigado senso mas já agora como estou a utilizar um motor shield, para controlaram direcção em que ele deve controlar os motores para efectuar a correcção devo apenas aplicar o valor de pwm num dos motores direita ou esquerda consoante. Quando tiver o codigo pronto meto-o aqui ora ver se esta tubo bem

rafasta

estava a ver os links que me deste senso e surgiu-me uma duvida. como determino os valorees de kP, ki e kd mais adequados para o meu projecto?

rafasta

este foi o codigo que a partir da net e de outros exemplos consegui criar. o arduino ja segue linhas mas agora nao sei como lidar com curvas a 90º e interrupçoes de linha. alguem tem alguma ideia. ja agora senso agradeço-te os links que colocas-te pois ajudaram-me a entender o que era o PID.
este é o meu codigo

#include <QTRSensors.h>

int PWMA=3; //pino pwm do motor 1
int PWMB=11; //pino pwm do motor 2
int DIRA=12; //pino de controlo do motor 1
int DIRB=13; //pino de controlo do motor 1

int lastError=0;

#define NUM_SENSORS   8   
#define TIMEOUT       2500 
#define EMITTER_PIN   QTR_NO_EMITTER_PIN   


QTRSensorsRC qtrrc((unsigned char[]) { 4, 5, 6, 7,14,15, 16, 17},
  NUM_SENSORS, TIMEOUT, EMITTER_PIN);
unsigned int sensors[NUM_SENSORS];

void setup()
{
//analogWrite(PWMA,255);
//analogWrite(PWMB,255);

delay(500);
  int i;
  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);   
  for (i = 0; i < 250; i++) 
  {
    qtrrc.calibrate();     
  }
  digitalWrite(13, LOW);   

  // print the calibration minimum values measured when emitters were on
  Serial.begin(9600);
  for (i = 0; i < NUM_SENSORS; i++)
  {
    Serial.print(qtrrc.calibratedMinimumOn[i]);
    Serial.print(' ');
  }
  Serial.println();
 
  // print the calibration maximum values measured when emitters were on
  for (i = 0; i < NUM_SENSORS; i++)
  {
    Serial.print(qtrrc.calibratedMaximumOn[i]);
    Serial.print(' ');
  }
  Serial.println();
  Serial.println();
  delay(1000);
}

void loop()

{

  unsigned int iPosition = qtrrc.readLine(sensors);
  unsigned int iError= iPosition-3500;
 
  int pd=0;
 
  float kP=0.1;             
  float kI=0;               
  float kD=0;

  int P = iError;             
  int I = 0;                 
  int D = iError-lastError; 
  lastError = iError;     
 
 
  int power_difference = (P*kP)+(I*kI)+(D*kD);
  int p_w;
  p_w= map(power_difference,-350, 350, -100,100);
   
   
 
    if (power_difference<0)
   {
    analogWrite(PWMA, 100 + p_w);
    analogWrite(PWMB, 100);
    digitalWrite(DIRA,LOW);
    digitalWrite(DIRB,HIGH);
   }

if (power_difference>0)
   {
    analogWrite(PWMA, 100);
    analogWrite(PWMB, 100-p_w);
    digitalWrite(DIRA,LOW);
    digitalWrite(DIRB,HIGH);
   }
}
  }

senso

O valores do KP, KI e KD são os coeficientes proporcionais, integrais e derivativos do controlador PID e dependem unica e exclusivamente do sistema que estás a controlar, ou seja, tens de afinar esses valores para o teu robot até obteres a melhor resposta.
O meu rato tem estes valores:

#define KP 0.42
#define KI 0.11
#define KD 0.11
Avr fanboy

rafasta

Mas como determino os melhores valores para o meu projecto?

senso

Vais afinando os valores até o robot não tremer/abanar devido a oscilações no loop de controlo, e que seja rápido o suficiente para nunca perder a linha.
Avr fanboy

rafasta

O que ocorre no meu énque ele começa bem (sem se afastar muito) mas vai-se progressivamente afastando até quase andar em semi-círculos em torno da linha. Qual dos valores devo alterar? Ou altero todos?

senso

Isso pode ser erro noutras partes do código, pois parece que está a acumular erros em algum sitio.
Avr fanboy

rafasta

Que outra parte do codigo? É que apenas tentei resolver este problema com os valores do kp, ki, kd , mas não sei que mais partes devo alterar

microbyte

Quote from: rafasta on 08 de April de 2012, 10:51
Que outra parte do codigo? É que apenas tentei resolver este problema com os valores do kp, ki, kd , mas não sei que mais partes devo alterar

Há código?
Mostra ai ao pessoal, senão ninguém te pode ajudar... ;)

senso

Não reparei que o que tinhas postado era o código total, cheira-me que tenhas o PID mal implementado, está demasiado simples.
Avr fanboy

rafasta

mycrobyte o codigo esta num dos post acima e sem ser pequenas alterações nos valores dos k's eu nao lhe mexi mais desde que o postei. muito simples? como assim senso? o que sugeres então que implemente no meu codigo

microbyte

Quote from: rafasta on 09 de April de 2012, 08:45
mycrobyte o codigo esta num dos post acima e sem ser pequenas alterações nos valores dos k's eu nao lhe mexi mais desde que o postei. muito simples? como assim senso? o que sugeres então que implemente no meu codigo
Tens toda a razão, eu não vi.

  int P = iError;             
  int I = 0;                 
  int D = iError-lastError; 
  lastError = iError;


O que faz isto aqui?
A parte proporcional está correcta.
A parte do integral não estás a calcular nada (foi propositado?)
A parte derivativa estás simplesmente a calcular uma diferenca entre o erro actual e o anterior (por definião, o termo derivativo é o declive destes dois pontos, em relação ao tempo decorrido)

Tens no link do senso um óptimo exemplo, bastante simples, que funciona no Arduino.
Ainda assim, porque não usas a biblioteca que o senso recomendou?