Go Down

Topic: Array de sensores CNY70, (Read 2 times) previous topic - next topic

Fred Gomes

Boas.
estou a efectuar um código para um seguidor de linhas, para isso tenho 5 sensores cny70 (não são cny70 mas são muito semelhantes e funcionam da mesma forma), e estou procurando obter um erro, e consoante esse erro o robot irá diminuir mais/menos a velocidade de um dos motores.

o que me acontece é que ao imprimir o valor do errorval este nunca me varia de 0.0, alguem em consegue ajudar e ver o que tenho de errado no código?

Code: [Select]
/* variaveis de utilizadas*/

const int nsensores = 5;
const int sensor[] = {2,3,4,5,6};
const int motor_right = 10;
const int motor_left = 11;

/* variaveis auxiliares*/

int senval[] = {0,0,0,0,0};
int vel_right = 0;
int vel_left = 0;
int maxvel = 200;
double errorval = 0.0;
boolean stop = false;

void setup(){
 Serial.begin(9600);
 pinMode (motor_right, OUTPUT);
 pinMode (motor_left, OUTPUT);
 pinMode (0, INPUT);
 pinMode (1, INPUT);
 pinMode (2, INPUT);
 pinMode (3, INPUT);
 pinMode (4, INPUT);
 digitalWrite (0, HIGH);
 digitalWrite (1, HIGH);
 digitalWrite (2, HIGH);
 digitalWrite (3, HIGH);
 digitalWrite (4, HIGH);
}
void loop(){
 
 //1º lemos o valor dos sensores
 readALLsensores();
 
 if(errorval < 0.0){
   vel_left = (int)(maxvel*(1-fabs(errorval)));
   vel_right = (int)(maxvel);
 }
 else if(errorval > 0.0){
   vel_left = (int)(maxvel);
   vel_right = (int)(maxvel*(1-errorval));
 }
 else{
   vel_left = (int)(maxvel);
   vel_right = (int)(maxvel);
 }
 //Fazer actuar os motores:
 analogWrite(motor_right,vel_right);
 analogWrite(motor_left, vel_left);

 delay(10);
 Serial.println(errorval);
 delay(500);

}

//FUNÇOES:
void readALLsensores(){
 for (int i=0; i < nsensores; i++)
 {
   senval[i] = digitalRead (sensor[i]);
 }
}

// escolher o sensor que esta sobre a linha
int bestsensor(int senval[])
{
 int best = 0;
 for (int i=0; i < nsensores; i++)
 {
   if(senval[i] == 1){
     best = i;    
   }
 }
 return best;
}
double error(int senval[])
{
 int best = bestsensor (senval);
 double lineError(int senVal[]);

 double error = 0.0;
 errorval = error;

 if (best== 0){
   error = -1.0;
 }
 else if(best== 1){
   error = -0.5;
 }
 else if( best == 2){
   error = 0.0;
 }
 else if(best == 3){
   error = 0.5;
 }
 else if(best == 4){
   error = 1.0;
 }
 return error;
}


experimentei também este código simples, e o errorval nunca m varia de 1.0, são coisas que eu não consigo perceber e perciso de ajuda, :

Code: [Select]
int sensor1 = 2;
int sensor2 = 3;
int sensor3 = 4;
int sensor4 = 5;
int sensor5 = 6;
double errorval = 0.0;

void setup(){
 Serial.begin(9600);
 digitalWrite(sensor1, HIGH);
 digitalWrite(sensor2,HIGH);
 digitalWrite(sensor3,HIGH);
 digitalWrite(sensor4,HIGH);
 digitalWrite(sensor5,HIGH);
}

void loop(){
 
 if(digitalRead(sensor1 == 1)){
   errorval = 1.0;
 }
 else if (digitalRead(sensor2 == 1)){
   errorval = 0.5;
 }
 else if (digitalRead(sensor3 == 1)){
   errorval = 0.0;
 }
 else if (digitalRead(sensor4 == 1)){
   errorval = -0.5;
 }
 else if(digitalRead (sensor5 == 1)){
   errorval = -1.0;
 }
 Serial.println(errorval);
 delay(500);
}



Italo Lima

No primeiro, vc não chama a função que atualiza o valor do erro. Por isso, o errorval continua com o valor inicial. 0.0.

Eu não consegui entender o porque de vc chamar a função digitalWrite (0, HIGH); quando vc quer que a porta funcione como uma entrada... Também, vc coloca as por 0~4 como input, mas depois lê as portas 2~6.

Att.

Radames

olá Fred,
como vc ligou os cny70 no arduino? vc tem um circuito amplificador com lm324?? ele veio com um circuito de suporte? mande os diagramas...

Fred Gomes

#3
May 17, 2010, 10:28 pm Last Edit: May 17, 2010, 10:30 pm by Fred_Gomes Reason: 1
ja alterei o código:

Code: [Select]
/* variaveis de utilizadas*/

const int nsensores = 5;
const int sensor[] = {2,3,4,5,6};
const int motor_right = 10;
const int motor_left = 11;

/* variaveis auxiliares*/

int senval[] = {0,0,0,0,0};
int vel_right = 0;
int vel_left = 0;
int maxvel = 200;
double errorval = 0.0;
boolean stop = false;

void setup(){
 Serial.begin(9600);
 pinMode (motor_right, OUTPUT);
 pinMode (motor_left, OUTPUT);
 pinMode (0, INPUT);
 pinMode (1, INPUT);
 pinMode (2, INPUT);
 pinMode (3, INPUT);
 pinMode (4, INPUT);
 digitalWrite (0, HIGH);
 digitalWrite (1, HIGH);
 digitalWrite (2, HIGH);
 digitalWrite (3, HIGH);
 digitalWrite (4, HIGH);
}
void loop(){

 //1º lemos o valor dos sensores

 ReadALLSensores();
 
 if(errorval < 0.0){
   vel_left = (int)(maxvel*(1-fabs(errorval)));
   vel_right = (int)(maxvel);
 }
 else if(errorval > 0.0){
   vel_left = (int)(maxvel);
   vel_right = (int)(maxvel*(1-errorval));
 }
 else{
   vel_left = (int)(maxvel);
   vel_right = (int)(maxvel);
 }
 //Fazer actuar os motores:
 analogWrite(motor_right,vel_right);
 analogWrite(motor_left, vel_left);

 delay(10);
 
 Serial.println(errorval);
 delay(500);

}
void readAllSensors(){
 for(int i=0; i < 5; i++)
 {
   senVal[i] = digitalRead(sensor[i]);
 }
}
 

// escolher o sensor que esta sobre a linha
double LineError(senval[])
{
 double error = 0.0;
int senval[] = {0,0,0,0,0};
 
for (int i=0; i < nsensores; i++)
 {
   senval[i] = digitalRead (sensor[i]);
 }
 if (senval) == 0b10000){
   error = -1.0;
 }
 else if (senval) == 0b11000){
   error = -0.75;
 }
 else if (senval) == 0b01000){
   error = -0.5;
 }
 else if (senval) == 0b01100){
   error = -0.25;
 }
 else if(senval) == 0b00100 || 0b01110){
   error = 0.0;
 }
 else if (senval) == 0b00110){
   error = 0.25;
 }
 else if(senval) == 0b00010){
   error = 0.5;
 }
 else if (senval) == 0b00011){
   error = 0.75;
 }
 else if (senval) == 0b00001){
   error = 1.0;
   }
 }
}



mas aponta -me erros nesta última função, alguem sabe a que se trata?

Italo Lima

Você pode colocar o erro que aparece?

É erro de compilação ou erro na hora de rodar?

Fred Gomes

#5
May 18, 2010, 12:45 am Last Edit: May 18, 2010, 12:50 am by Fred_Gomes Reason: 1
era erro de compilação..
bem, já aqui tenho o código um bocado alterado (com a ajuda de membros fo forum "Lusorobotica" , só que não consigo fazer com o valorsensor seja apenas zeros e uns, pois também aparecem zeros, alguem sabe trabalhar bem com o sistema binário no arduino? e saber assim o que esta errado neste códido que me provoca uma má leitura do erro..

Code: [Select]
/* variaveis de utilizadas*/

const int nsensores = 5;
const int sensor[] = {2,3,4,5,6};
const int motor_right = 10;
const int motor_left = 11;

/* variaveis auxiliares*/

int senval[] = {0,0,0,0,0};
int vel_right = 0;
int vel_left = 0;
int maxvel = 200;
double errorval = 0.0;
boolean stop = false;

void setup(){
 Serial.begin(9600);
 pinMode (motor_right, OUTPUT);
 pinMode (motor_left, OUTPUT);
 pinMode (2, INPUT);      
 pinMode (3, INPUT);      
 pinMode (4, INPUT);      
 pinMode (5, INPUT);
 pinMode (6, INPUT);
 digitalWrite (2, HIGH);
 digitalWrite (3, HIGH);
 digitalWrite (4, HIGH);
 digitalWrite (5, HIGH);
 digitalWrite (6, HIGH);
}
void loop(){

 
errorval = LineError();  
 if(errorval < 0.0){
   vel_left = (int)(maxvel*(1-fabs(errorval)));
   vel_right = (int)(maxvel);
 }
 else if(errorval > 0.0){
   vel_left = (int)(maxvel);
   vel_right = (int)(maxvel*(1-errorval));
 }
 else{
   vel_left = (int)(maxvel);
   vel_right = (int)(maxvel);
 }
 //Fazer actuar os motores:
 analogWrite(motor_right,vel_right);
 analogWrite(motor_left, vel_left);

 delay(10);
 

}

// escolher o sensor que esta sobre a linha

double LineError()
{
 double error = 0.0;
 for (int i=5; i < nsensores; i++){
 
   senval[i] = digitalRead (sensor[i]);
   Serial.println (senval[i]);
   delay(500);
 }
 unsigned int valorsensor=senval[2]+senval[3]<<3+senval[4]<<4+senval[5]<<5+senval[6]<<6;   //o que isto faz é juntar os valores do array senval num numero só                                 //assim já podes fazer as comparações nos if's
 if (valorsensor== 0b10000){
   error = -1.0;
 }
 else if (valorsensor == 0b11000){
   error = -0.75;
 }
 else if (valorsensor == 0b01000){
   error = -0.5;
 }
 else if (valorsensor == 0b01100){
   error = -0.25;
 }
 else if(valorsensor == (0b00100 || 0b01110)){
   error = 0.0;
 }
 else if (valorsensor == 0b00110){
   error = 0.25;
 }
 else if (valorsensor == 0b00010){
   error = 0.5;
 }
 else if (valorsensor == 0b00011){
   error = 0.75;
 }
 else if (valorsensor == 0b00001){
   error = 1.0;
 }
 Serial.println(valorsensor);
 delay(200);

 return error;
}

tarcardoso

Observe o seguinte codigo dentro do metodo: double error(int senval[])

...
 double error = 0.0;
 errorval = error;
....
voce esta atribuindo o valor 0.0 a variavel erro, depois atribuindo a variavel ao errorval, ou seja errorval esta ficando igual a zero.

Ou seja, a variavel (neste caso global) errorval vai ficar sempre zero.

Se esta trabalhando com uma variavel global, voce pode tratar ela sem a necessidade de uma função que retorna algum valor.

Recomendo retirar a variavel local error da função double error(int senval[]).

Qualquer coisa entre em contato.

tarcardoso

Sobre a segunda questão:

Cara você tem que ter enfoque na solução, não no problema. Porque motivo esta trabalhando com binário e fazendo operação de bit.........a  não ser que esteja estudando esses tipos de operações....
A única coisa que tem que fazer e verificar qual o sensor que esta com o maior valor(ou menor) para descobrir qual o sensor esta mais próximo da linha.

Outra coisa, coloque nome de métodos mais descritivo, lineError que dizer algum erro mais nada haver com "escolhe sensor que esta sobre a linha", desculpe mais seu código esta muito ruim, você poderia ter colocando o método simplesmente como escolhe_senser_que_esta_sobre_a_linha(), garanto a você que qualquer um conseguiria entender.

Outra coisa é sobre essa operação de igualdade.....veja bem o que esta fazendo.....eu não vou nem comentar.

Segue um codigo so para mostrar como pode ser feito:

int escolhe_sensor_que_esta_sobre_a_linha(){
     int sensor = 0;
     double error = 0.0;
     //busca pelo sensor que esta mais proximo da linha, ou seja, esta captando valor mais escuro
 for (int i=5; i < nsensores; i++){
     int valor = digitalRead (sensor);
     if( valor > sensor){
      sensor = valor;
     }
 }
 return sensor;
}




Fred Gomes

Boas.
eu ainda começei à pouco tempo a mexer no arduino, tenho algumas dificuldades de programação..

se eu fizer como dizes ( a escolher o sensor que esta mais próximo da linha), eu não vou poder ter mais que 1 sensor sobre a linha, e isso muitas das vezes vai acontecer, daí optar por  fazer a leitura do array (em binário), mas ´coidog não funciona,

eu consigo ler o senval correctamente, mas o valorsensor é sempre 0, juntamente com error..

Italo Lima

O que vc precisa está mais ou menos nessa página:
http://arduino.cc/en/Reference/Bitshift

Ficaria mais ou menos assim:
byte sensores = 0;
FOR DE LEITURA
 sensores = (sensores << 1) + digitalRead(sensor[...]);
END

no começo o sensores == B00000000. Cada vez que vc usa o sensores<<1 ele desloca todos os bits na direção da seta por uma casa(acrescentado um 0 no espaço novo). O resultado de digital... é sempre 1 ou 0.
Digamos que o primeiro sensor retornou 1. Então
ERA sensores == B00000000
sensores << 1 não muda nada
digital... retorna 1, então no final
sensores = B00000001

O segundo leitor retornou 0, do mesmo modo,
sensores << 1 retorna B00000010
somando com o digital...
retorna B00000010.

E assim por diante. O resultado então de sensores vai ser
B000ABCDE
Onde A primeiro sensor, B segundo,...

Só que, toda essa parafernalha com bits só é útil para poupar espaço na memória do arduino.
Se a memória não for um fator limitante, basta fazer como vc estava antes, armazenando tudo em um array, e depois verificar cada caso com &&

Se vc quiser saber se só o primeiro e segundo estão retornando 1,
Code: [Select]

if((sensores[0] == 1) &&
  (sensores[1] == 1) &&
  (sensores[2] == 0) &&
  (sensores[3] == 0) &&
  (sensores[4] == 0)     )


Pensa um pouco a respeito e vê se consegue resolver.

Italo Lima

P.S.: Acho que a parafernalha com bits também adicionaria um pouquinho de velocidade às operações. Ainda assim, acho que não seria uma diferença perceptível no seu caso.

Fred Gomes

eu não percebi bem o que isto faz:

if((sensores[0] == 1) &&
  (sensores[1] == 1) &&
  (sensores[2] == 0) &&
  (sensores[3] == 0) &&
  (sensores[4] == 0)     )


o código que apresento asseguir já me retorna bem os valores em binário (imprindo os valores em binário em décima),

Code: [Select]
/* variaveis de utilizadas*/

const int nsensores = 5;
const int sensor[] = {2,3,4,5,6};
const int motor_right = 10;
const int motor_left = 11;

/* variaveis auxiliares*/

int senval[] = {0,0,0,0,0};
int vel_right = 0;
int vel_left = 0;
int maxvel = 200;
double errorval = 0.0;
boolean stop = false;

void setup(){
 Serial.begin(9600);
 pinMode (motor_right, OUTPUT);
 pinMode (motor_left, OUTPUT);
 pinMode (2, INPUT);    
 pinMode (3, INPUT);    
 pinMode (4, INPUT);    
 pinMode (5, INPUT);
 pinMode (6, INPUT);
 digitalWrite (2, HIGH);
 digitalWrite (3, HIGH);
 digitalWrite (4, HIGH);
 digitalWrite (5, HIGH);
 digitalWrite (6, HIGH);
}
void loop(){
errorval = LineError();



 if(errorval < 0.0){
   vel_left = (int)(maxvel*(1-fabs(errorval)));
   vel_right = (int)(maxvel);
 }
 else if(errorval > 0.0){
   vel_left = (int)(maxvel);
   vel_right = (int)(maxvel*(1-errorval));
 }
 else{
   vel_left = (int)(maxvel);
   vel_right = (int)(maxvel);
 }
 //Fazer actuar os motores:
 analogWrite(motor_right,vel_right);
 analogWrite(motor_left, vel_left);

 delay(200);

}

// escolher o sensor que esta sobre a linha

double LineError()
{
 double error = 0.0;
 int valorsensor = 0;
 for (int i=0; i < nsensores; i++){
 
   senval[i] = digitalRead (sensor[i]);
 }
 valorsensor = (senval[0]) | (senval[1]<<1) | (senval[2]<<2) | (senval[3]<<3) | (senval[4]<<4);
 Serial.println ("valor do sensor");
 Serial.println(valorsensor);
 delay(500);


 if (valorsensor== 0b10000){
   error = -1.0;
 }
 else if (valorsensor == 0b11000){
   error = -0.75;
 }
 else if (valorsensor == 0b01000){
   error = -0.5;
 }
 else if (valorsensor == 0b01100){
   error = -0.25;
 }
 else if((valorsensor==0b00100) || (0b01110)){
   error = 0.0;
 }
 else if (valorsensor == 0b00110){
   error = 0.25;
 }
 else if (valorsensor == 0b00010){
   error = 0.5;
 }
 else if (valorsensor == 0b00011){
   error = 0.75;
 }
 else if (valorsensor == 0b00001){
   error = 1.0;
 }
 return error;
}


já experimentei colocar o valor décimal nos IF´s (equivalente ao valor em binário), mas o error nunca me varia de 0.0 não sei pq..
no entanto já obtenho os valores que necessito, so me falta resolver este problema..

Italo Lima

Nesse caso, o problema tá na linha:
Code: [Select]
 else if((valorsensor==0b00100) || (0b01110)){
   error = 0.0;
 }


Olha com mais cuidado a condição do if:
Code: [Select]
(valorsensor==0b00100) || (0b01110)
Ela é composta por duas partes:
Code: [Select]
(valorsensor==0b00100)
e
Code: [Select]
(0b01110)
ligados pelo ||.

A primeira, retorna se a igualdade é verdadeira ou não. A segunda, não tem nenhuma comparação, é só o valor puro (diferente de 0). Lembrando que 0 é  falso e qualquer coisa diferente é verdadeiro, qual o resultado da avaliação da condição do seu if?

O trecho que vc não entendeu faz exatamente o que eu disse:
vê se a resposta do primeiro e segundo senssores é 1 e o resto é 0.
Conheçe o &&?

Fred Gomes

oh,
eu entendi sim..
eu conheço o &&, eu disse que não estava entendendo pq vc fez isso em linhas separadas, e eu estou habituado numa so linha..

mas pq necessito eu desses and´s?,

eu aqui:
Code: [Select]
(valorsensor==0b00100) || (0b01110) o que o arduino vai fazer é se valorsensor == 0b00100/ab1110,

não percebo qual o problema..
eu obtenho os algarismos (em decima), do array em binário que estou usando, como coloco isso agora para me gerar um erro?, não bastaria colocar um seguimento de IF´s para esse svalores ?

algo do tipo:

Code: [Select]
se (31){ error = 0.0;
o código está mal escrito, mas é so para  me fazer perceber, não bastaria fazer apenas algo assim? é que eu ja fiz isso e o error nunca sai de 0.0 não sei pq..

Italo Lima

Separei as linhas sem nenhum motivo especial. Só pq ficou um pouco mais fácil de digitar.

O problema é exatamente esse.
Code: [Select]
(valorsensor==0b00100) || (0b01110)
Isso não avalia o que vc está achando.
Para ser do jeito que vc quer, deveria ser:
Code: [Select]
(valorsensor==0b00100) || (valorsensor=0b01110)

Tenta entender a diferença. Acho que vc ainda não chegou bem no ponto do que significa || e &&.

Qqer coisa, fala.

Go Up