Go Down

Topic: QTR-8RC reflectance sensor (Read 3192 times) previous topic - next topic

Fred Gomes

Boa tarde.
estou a tentar construir um seguidor de linhas usando um array de 8 sensores RC, da Pololu, estou a tentar usar a biblioteca fornecida pela Pololu, mas não consigo proceder à leitura dos sensores, o único valor que consigo obter no ecra Serial é 0:/

os links da biblioteca em que me centrei são os seguintes:

http://www.pololu.com/docs/0J18/14
http://www.pololu.com/docs/0J19/3

e o código que idealizei foi:

Code: [Select]
#include <PololuQTRSensors.h>

PololuQTRSensorsRC qtrrc((unsigned char[]) {2, 3, 4, 5, 6,7,8,9}, 8);
 
void setup(){
 Serial.begin(9600);
 int i;
 for ( i = 0; i < 250; i++){
   qtrrc.calibrate();
   delay(20);
 }
}

void loop(){
 qtrrc_read();
 // Imprimir os valores dos sensores.
 for (int i = 0; i < 8; i++){
   Serial.println (val_sensores[i]);
   delay(500);
 }
}
void qtrrc_read(unsigned int *vsensores, unsigned char readMode){
 
 for (int i=0; i < 8; i++){
   val_sensor[i] = qtrrc.read(vsensores[i]);
   delay(50);
 }
}


o compilador acusa-me um erro, diz que tenho muitas funções em função de void loop(){ , não percebo pq..

conseguem ajudar-me?
cumps
Fred

arilson

    Na documentação da biblioteca fala a respeito das funções de calibração, pode ter algo aí

    Outro coisa, sempre que começo a trabalhar com algo novo, como é o caso, utilizo  apenas um sensor, e tento saber o máximo sobre ele, depois replico a experiência, comigo sempre funciona!

Radames

Olá Fred,

Este é o código que você esta tentando compilar?
Bom, seria interessante passar o código completo, pelo que vejo neste ai faltam varias definições das portas onde os sensores supostamente deveriam estar. Mande o código completo!

Fred Gomes

Boas.
já consegui fazer a leitura dos sensores, utilizei o seguinte código:

Code: [Select]
#include <PololuQTRSensors.h>

   PololuQTRSensorsRC qtr((unsigned char[]) {9,8,7,6,5,4,3,2}, 8);

   void setup()
   {
     Serial.begin(9600);
   }

   void loop()
   {
     unsigned int readings[8];
     qtr.read(readings);
     Serial.print ("sensor1  ");
     Serial.println(readings[0]);
     delay(1000);
     Serial.print ("sensor2  ");
     Serial.println(readings[1]);
     delay(1000);
     Serial.print ("sensor3  ");
     Serial.println(readings[2]);
     delay(1000);
     Serial.print ("sensor4  ");
     Serial.println(readings[3]);
     delay(1000);
     Serial.print ("sensor5  ");
     Serial.println(readings[4]);
     delay(1000);
     Serial.print ("sensor6  ");
     Serial.println(readings[5]);
     delay(1000);
     Serial.print ("sensor7  ");
     Serial.println(readings[6]);
     delay(1000);
     Serial.print ("sensor8  ");
     Serial.println(readings[7]);
     delay(1000);
   }

   




agora, estou tentando fazer mover os motores consoante o código, eu ja fiz um código que calcula o erro e faz girar os motores mais ou menos consoante o erro, mas esse código só funciona em leituras digitais,

para usar estes sensores necessito de fazer leituras que a própia biblioteca define, eu ainda não percebi como essa biblioteca cálcula o erro automaticamente...

vou postar o código que fiz ( não funciona não sei porque), dizer porque tomei algumas decisões, e agradeçia muito a vossa ajuda...

Code: [Select]
#include <PololuQTRSensors.h>

PololuQTRSensorsRC qtr((unsigned char[]) {9,8,7,6,5,4,3,2}, 8);
int motor_right = 9;
int motor_left = 10;

//variaveis auxiliares.

int ltarguetval = 0;// valor a desejar no motor left.
int rtarguetval = 0;// valor a desejar no motor right.
int lnowval = 0;    // valor actual no motor left.
int rnowval = 0;    // valor actual no motor right.

void setup(){
 Serial.begin(9600);
 
 pinMode (motor_right, OUTPUT);
 pinMode (motor_left, OUTPUT);

 int i;
 for (i = 0; i < 250; i++)
 {
   qtr.calibrate();
   delay(20);
 }
}


void loop(){
 unsigned int sensors [8];
 int position = qtr.readLine(sensors);
 int error = position -1000;
 int lastError = 0;
 int maxspeed = 130;
 double KP = 0.1;
 int KD = 5;
 int motorspeed = KP * error + KD * (error - lastError);
 lastError = error;
 
 Serial.print (qtr.readLine (sensors));
 delay(500);


 if(sensors[3] > 750 && sensors[4] > 750)
 {
   return;
 }

if (error = 0){
  rtarguetval = (int)maxspeed;
  ltarguetval = (int) maxspeed;
}
else if (error < 0 ){
   rtarguetval = (int)motorspeed;
   error = lastError;
 }
 else if ( error > 0){
   ltarguetval = (int)motorspeed;
   error = lastError;
 }
}


   


bem , eu tenho 8 sensores, e eu acho que deve haver uma "função" que permite indicar o meu estado ideal dos sensores, isto é, o estado a que os sensores devem estar para os motores andarem à máxima velocidade, e que nesse apenas nesse estado o erro seja 0., eu defini isso aqui:

Code: [Select]
if(sensors[3] > 750 && sensors[4] > 750)
 {
   return;
 }
, desejo que apenas os dois sensores do meio vejam preto, isto está correcto? (eu acho que não, mas não encontro outra forma de fazer isto, por isso estou pedinso a vossa ajuda),

e entendi que se esse fragmento não se verificasse existiria um erro, erro esse que iria determinar a velocidade dos motores..

se me conseguirem ajudar agradçeia imenso..


Radames

qual é este erro que você quer calcular?
quais os sensores no array sensors[] ativam quais motores?
você quer apenas detectar valores acima de 750? isso implica claro ou escuro certo?
Baseado nisso posso te ajudar a criar uma função que dado os sensors e sensors[j] , ele move o robo para das direções desejadas

Fred Gomes

vê este link:

http://www.pololu.com/docs/0J19/3

eu coloquei 750 porque foi o que vi no código ( se tiver valores muito altos, os sensores estão sobre o preto, e vice versa, o valor dos sensores varia entre 0-4000).

a minha duvida mantêm-se, eu ali coloquei para fazer return quando o sensor 3 e 4 vir um valor acima de 750, porque entendi que esse valor é o valor dos sensores que eu quero que veja preto (mas volto a dizer, penso que isso está mal), daí pergunto, de todas as instruções da Pololu, como eu defino "o meu estado ideal " do robot, ou seja, o estado que os sensores devem estar para os dois motores girarem à maxima velocidade,

e quando esse estaod não se verifique exista um erro, que faça um determinado motor (curva pouco apertada) abrandar pouco, ou então abrandar muito (cruva muito apertada) e assim o robot fazer as curvas de forma perfeita!

(link das funções da Pololu)

http://www.pololu.com/docs/0J18/14

eu já concretizei um código para usar com 5 sensores "normais" (leitura digital) e calculo o erro manualmente, mas com as funções da Pololu esse erro pode ser calculado automaticamente, e é essa a minha duvida ainda, como ele é calculado..

se quiseres que deixe aqui esse código que fiz para o poderes ver diz, eu já tentei adaptar esse codigo a estes sensores ( em vez de ver valores digitais coloquei o valor 4000 (que é quando estes sensores estão mesmo sobre o preto), mas o compilador aponta muitos erros, pois a forma de leiitura destes sensores também é diferente "dos normais" e o compilador não deve aceitar isso..


Radames

Olá Fred,
Então, lendo a documentação ficou mais claro,
vou te explicar
O método readLine lê o estado de todos os sensores, atualiza o array de entrada no seu caso sensors[], depois retorna a posição estimada da linha abaixo do seu sensor.
no seu caso com 8 sensores temos
Code: [Select]

void loop(){
 unsigned int sensors [8];
 int position = qtr.readLine(sensors);


 /'position tem um valor dado por

 0     *leitura_sensor1 + 1000*leitura_sensor2
 2000*leitura_sensor3 + 3000*leitura_sensor4
 4000*leitura_sensor5 + 5000*leitura_sensor6
 6000*leitura_sensor7 + 7000*leitura_sensor8
 
 Portanto , se position = 0, a linha preta esta abaixo do sensor1,
 se position = 5000 ,  a linha preta esta abaixo do sensor 6, e assim
 por diante.
 position vai de 0 a 7000;

 a função erro, ele faz no exemplo para ajustar a posição dos sensores no robô, isso depende da geometria do seu sistema, por exemplo se você colocou esse array de sensores no meio do seu robô, provavelmente estará interessado nisso,

-3500 -2500 -1500 0 1500 2500 3500, onde o 0 é o meio entre os sensores 0,3 e 4,7 , certo?

portanto sua função erro vai ser


/*
 int error = position -3500;

//pronto agora vc pode verificar o seguinte

if(error > 1000){ // qualquer valor acima de 1000
 //algum dos sensores da direta esta ativado
 motor_direira();// funcao que ativa o motor da direita
}
if(error < -1000){ // qualquer valor acima de -1000
 //algum dos sensores da esquerda esta ativado
 motor_esquerda();// funcao que ativa o motor da esquerda
}



Note que desta maneira você esta avaliando se algo esta ocorrendo em média do lado esquerdo e do lado direito, mas você ainda tem a informação de qual sensor , dos 8, estão com uma linha em baixo ou não..
você poderia fazer um robô com trajetórias complexas., seguindo varias linhas!
Espero ter ajudado!

qualquer coisa estamos por ai
até!

Fred Gomes

Boas.
isto aqui: -3500 -2500 -1500 0 1500 2500 3500, onde o 0 é o meio entre os sensores 0,3 e 4,7 , certo?

porque colocaste os valores de -3500 a 3500?

eu fiz esta programação, mas não funciona, talvez o meu erro venha daí..

Code: [Select]
#include <PololuQTRSensors.h>

PololuQTRSensorsRC qtr((unsigned char[]) {9,8,7,6,5,4,3,2}, 8);
int motor_right = 9;
int motor_left = 10;

//variaveis auxiliares.

int ltarguetval = 0;// valor a desejar no motor left.
int rtarguetval = 0;// valor a desejar no motor right.
int lnowval = 0;    // valor actual no motor left.
int rnowval = 0;    // valor actual no motor right.

void setup(){
 Serial.begin(9600);

 pinMode (motor_right, OUTPUT);
 pinMode (motor_left, OUTPUT);

 int i;
 for (i = 0; i < 250; i++)
 {
   qtr.calibrate();
   delay(20);
 }
}


void loop(){
 unsigned int sensors [8];
 int position = qtr.readLine(sensors);
 int error = position -3500;
 int lastError = 0;
 int maxspeed = 130;
 double KP = 0.1;
 int KD = 5;
 int motorspeed = KP * error + KD * (error - lastError);
 lastError = error;

 Serial.println (qtr.readLine (sensors));
 delay(500);


 if(sensors[3] > 750 && sensors[4] > 750)
 {
   return;
 }

if (error = 0){
  rtarguetval = (int)maxspeed;
  ltarguetval = (int) maxspeed;
}
else if (error < 3500 ){
   ltarguetval = (int)motorspeed;
   rtarguetval = maxspeed;
   error = lastError;
 }
 else if ( error > 3500){
   rtarguetval = (int)motorspeed;
   ltarguetval = maxspeed;
   error = lastError;
 }
   if(rtarguetval > rnowval){
   rnowval +=1;
 }else if (rtarguetval < rnowval){
   rnowval -=1;
 }
 if (ltarguetval > lnowval){
   lnowval +=1;
 }else if(ltarguetval < lnowval){
   lnowval -=1;
 }
}


diz o que achas do meu código, e erros que aches que possam estar afectar o mau funcionamento do robot indicamos, ou mesmo corrige mos sff..

outra coisa..
quando estou a fazer o readline, se colocar o dedo em cima do sensor 7, obtenho o valor 7000, o do lado, 6000, mas os outros nunca altera o valor, de vez em quando altera mas para valores pouco fiaveis, ou zeros, ou 4000, fico sem perceber porque.. no entanto confiremei as ligações dos sensores e estão todas correctas..

consegues ajudar me?

Fred Gomes

ahh! e explica me isto "onde o 0 é o meio entre os sensores 0,3 e 4,7 , certo?" não percebi...

o que eu quero que o robot faça é que ambos os motores girem à maxima velocidade quando tiver os dois sensores do meio no preto(sensor 3 e 4), não percebi o que disseste..

depois vê o meu codigo e tenta corrigit me sff..
Obrigado pela ajuda Radamés.

Radames

Olá Fred,
então quando position = 0 , isto é o sensor zero supostamente tampado e todos os outros aberto, o error = position - 3500, isto dá , erro = -3500, outro caso, quando a position = 3000, isto é o sensor 4 esta tampado e todos os outro aberto, error = 500, no final eu havia errado, os valores corretos para o erro, com centro nos sensores, 3 e 4  serão.
-3500  -2500 -1500 -500 500 1500 2500 3500
entende?


para o motor a maxima velocidade com a linha entre 3 e 4 eu faria

Code: [Select]
if(error >-500 && error < 500){
 motor na maxima velocidade
}else if(error > 500){
 liga motor da direita e desliga esquerda, talvez?!??!

}else if(error<-500){
 liga motor da esquerda e desliga o da direita, ??!??!
}


acho que é isso!
até!

Fred Gomes

mas não funciona:/
eu tenho os 8 sensores ligados, e ao colocar o meu dedo por cima dum sensor (um a um) o qtr.readline não me indica os valores esperados (0, 1000, 2000, etc), no entanto vai variando...
podemos trocar e-mails para me poderes ajudar melhor?

Fred Gomes

isto protasse duma forma muito estranho...
por exemplo, eu tinha o Serial monitor aberto, e colocava um objecto preto sobre o sensor 7, e dava me o valor 7000, 6, 6000 etc....

fecho o Serial monitor e volto abrir e so me gera zeros :-/ , porque acontece isso?estou mesmo sem saber o que fazer...

fiz este simples código so para ler o valor dos sensores:

Code: [Select]
#include <PololuQTRSensors.h>

PololuQTRSensorsRC qtr((unsigned char[]) {9,8,7,6,5,4,3,2}, 8);

void setup(){
 Serial.begin(9600);
 int i;
 for (i = 0; i < 250; i++)
 {
   qtr.calibrate();
   delay(20);
 }
}

void loop(){
 
 unsigned int sensors [8];
 int position = qtr.readLine(sensors);
 
 Serial.println (qtr.readLine (sensors));
 delay(500);
}
 


os unicos valores que obtenho são zeros..:S perciso mesmo de ajuda...

Radames

entre em contato comigo por email!
radamajna at gmail dot com

Fred Gomes

#13
Mar 28, 2010, 01:18 pm Last Edit: Mar 28, 2010, 08:14 pm by Fred_Gomes Reason: 1
ja adicionei você,
se não receber nada diga algo por aqui...
obrigado pela disponibilidade radames ;)

Fred Gomes

Boas.
acho que já sei onfde esta o meu erro na programação..
aqui : "-3500  -2500 -1500 -500 500 1500 2500 3500 ", eu nao defini isto no meu código, podes me dizer como defino estes valores de erro para o meu codigo??..

vê este código:

Code: [Select]
#include <PololuQTRSensors.h>

PololuQTRSensorsRC qtr((unsigned char[]) {9,8,7,6,5,4,3,2}, 8);
int motor_right = 9;
int motor_left = 10;

//variaveis auxiliares.

int ltarguetval = 0;// valor a desejar no motor left.
int rtarguetval = 0;// valor a desejar no motor right.
int lnowval = 0;    // valor actual no motor left.
int rnowval = 0;    // valor actual no motor right.

void setup(){
 Serial.begin(9600);

 pinMode (motor_right, OUTPUT);
 pinMode (motor_left, OUTPUT);

 int i;
 for (i = 0; i < 250; i++)
 {
   qtr.calibrate();
   delay(20);
 }
}


void loop(){
 unsigned int sensors [8];
 int position = qtr.readLine(sensors);
 int error = position -3500;
 int lastError = 0;
 int maxspeed = 130;
 double KP = 0.1;
 int KD = 5;
 int motorspeed = KP * error + KD * (error - lastError);
 lastError = error;

 Serial.println (qtr.readLine (sensors));
 delay(500);


 if(sensors[3] > 750 && sensors[4] > 750)
 {
   return;
 }

if (error = 0){
  rtarguetval = (int)maxspeed;
  ltarguetval = (int) maxspeed;
}
else if (error < 3500 ){
   ltarguetval = (int)motorspeed;
   rtarguetval = maxspeed;
   error = lastError;
 }
 else if ( error > 3500){
   rtarguetval = (int)motorspeed;
   ltarguetval = maxspeed;
   error = lastError;
 }
   if(rtarguetval > rnowval){
   rnowval +=1;
 }else if (rtarguetval < rnowval){
   rnowval -=1;
 }
 if (ltarguetval > lnowval){
   lnowval +=1;
 }else if(ltarguetval < lnowval){
   lnowval -=1;
 }
}


esses valores não estão ai declarados pois não? apenas declaro o -3500, como declaro os outros??.. perciso de os declarar para que "ele saiba" que para os valores -500 e 500 tenho o sensor 3 e 4..

Go Up