Array de sensores CNY70,

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?

/* 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, :

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);
}

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.

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...

ja alterei o código:

/* 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?

Você pode colocar o erro que aparece?

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

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…

/* 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;
}

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.

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;*
    }

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..

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,

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.

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.

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),

/* 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…

Nesse caso, o problema tá na linha:

  else if((valorsensor==0b00100) || (0b01110)){
    error = 0.0;
  }

Olha com mais cuidado a condição do if:

(valorsensor==0b00100) || (0b01110)

Ela é composta por duas partes:

(valorsensor==0b00100)

e

(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 &&?

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:(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:

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..

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

O problema é exatamente esse.

(valorsensor==0b00100) || (0b01110)

Isso não avalia o que vc está achando. Para ser do jeito que vc quer, deveria ser:

(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.

ahh.. eu já percebi o que queres dizer.. era para alterar o meu código e deixar de usar os valores binários não é? , por causaimo código da minha dúvida anterior..

mas essa questão já está resolvida, vê o último código que eu deixei, eu é-me retornado um valor décimal (valor décima respectivo ao valor em binário que o senval[] contêm (não te esqueças que estou a efectuar uma leitura digital).

e a minha dúvida agora é consoante o valor biinário/decimal que eu obtenho quero obter um erro (podes ver na programação),

e o que eu queria que me ajudasses era a resolver este meu problema, já experimentei colocar um seguimento de IF´s para o valor decimal(respectivo ao codigo em binario que tenho na programação ) , e em função desse valor decimal obter um erro, mas ao fazer o print de error este nunca me varia de 0.0, sabes pq isso aocntece?.. era ai que queria que me ajudasses..

quanto a isto:

(valorsensor==0b00100) || (valorsensor=0b01110)

eu estava a pensar que o que eu estava a fazer ia fazer: se valor sensor = XXX, OU YYY, ao fazer o OU ele ia substituir o que estava em XXX por YYY e se se verifica-se apenas um destes casos ele efectuava aquela condição..

mas vou expeirmentar como disseste.. ja digo os resultados..

/* 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);
  Serial.println(errorval);

}
 
// 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){
    valorsensor = 16;
    error = -1.0;
  }
  else if (valorsensor == 0b11000){
    valorsensor = 24;
    error = -0.75;
  }
  else if (valorsensor == 0b01000){
    valorsensor = 8;
    error = -0.5;
  }
  else if (valorsensor == 0b01100){
    valorsensor = 12;
    error = -0.25;
  }
  else if((valorsensor==0b00100) || (valorsensor=0b01110)){
    valorsensor = 4 ||14;
    error = 0.0;
  }
  else if (valorsensor == 0b00110){
    valorsensor = 6;
    error = 0.25;
  }
  else if (valorsensor == 0b00010){
    valorsensor = 2;
    error = 0.5;
  }
  else if (valorsensor == 0b00011){
    valorsensor = 3;
    error = 0.75;
  }
  else if (valorsensor == 0b00001){
    valorsensor = 1;
    error = 1.0;
   
  }
  return error;
}

devia funcionar, e o error não me varia de 0.0…

Problema na mesma linha :)

olha as igualdades. Tem um == e um =.

é isso:D já funciona...

muito obrigado pela ajuda...

olha, se quiseres , tens aqui um forum muito fixe..: lusorobotica.com , de robotica..

podemos encontrar-nos lá;) e ves lá o meu projecto final de curso que ando a construir..