Lectura de sonar HC-SR04

Hola @Liskarra0, bienvenido al foro Arduino en Español.

Te invito a que leas las Normas del foro y luego edites tu post inicial

Si observas, he modificado tu segundo post porque repites lo que se lee en el primero. No lo hagas, eso se considera una falta menor pero falta al fin a las normas. Manten el hilo limpio de comentarios repetidos.

Solo usa quote o cita para resaltar un párrafo de quien te responda, pero no TODA su respuesta. Simple no?

Bueno, las cosas no funcionan porque se han agregado tiempos y éstos alternan los comportamientos que conocías.

Igualmente colocas los dos codigos por separado pero no se ve el código de como esta ahora el conjunto. Usa etiquetas.

El moderador te ha regañado ya por no leer las NORMAS, y vas y posteas el código de la misma manera...

Hola surbyte, gracias por contestarme.

No entiendo a que te refieres con añadir tiempos. Como ya comente el programa funcionaba perfectamente cuando en el loop escribía yo que rutina utilizar. Sin embargo al añadir la pixy2 para la elección de la rutina las mediciones del sonar eran erroneas.

Adjunto el código entero para que puedas entender mejor el programa.

Muchas gracias de antemano.

#include 
#include 
#include 

// SONARRAREN PINAK
    #define trigPin 50 // Arduino pin tied to trigger pin on the ultrasonic sensor.    
    #define echoPin 48    // Arduino pin tied to echo pin on the ultrasonic sensor.
    #define led 46
   
// PI-ren ezarpena
    #define PI 3.1415926535897932384626433832795
     
int encoderPos=0;
AF_DCMotor aurezk(4,MOTOR34_64KHZ); // Rueda delantera izquierda 
AF_DCMotor auresk(3,MOTOR34_64KHZ); // Rueda delantera derecha 
AF_DCMotor atzesk(1,MOTOR12_64KHZ); // Rueda trasera derecha
AF_DCMotor atzezk(2,MOTOR12_64KHZ); // Rueda trasera izquierda 
Servo servoMotor;
Pixy2 pixy; 



void setup()
{
          Serial.begin(9600); 
          pinMode(trigPin, OUTPUT);
          pinMode(echoPin, INPUT);
          pinMode(led, OUTPUT);
          pinMode(52,OUTPUT);
          attachInterrupt(2, interrupcion, FALLING);
          pixy.init(); // Inicializacion de la camara Pixy2
}

void loop()
{
 Serial.println("ITXAROTEN");
 pixy.ccc.getBlocks(); // Recoger datos de la camara
 if(pixy.ccc.numBlocks) // Para comprobar si ha detectado algo 
 {
   
   if(pixy.ccc.blocks[0].m_signature==1) // Color uno detectado 
   {
     Abat(); // Ir a A1
   }
   else if(pixy.ccc.blocks[0].m_signature==2) // Color dos detectado
   {
     Abi();   // Ir a A2
   }
   else if(pixy.ccc.blocks[0].m_signature==3) // Color. 3 detectado
   {
     digitalWrite(30,HIGH);
   }
   
 }
}



void interrupcion()
{
 encoderPos++;
}




void JATORRItikAP()
{

int angelua; //angulo del servo
int aldaketa; // variable para cambiar el angulo
double minimoa; //distancia mínima para colision

// establecer velocidades
atzezk.setSpeed(100);
atzesk.setSpeed(100);
aurezk.setSpeed(100);
auresk.setSpeed(100);

long distancia;
distancia=0;
encoderPos=0;
angelua=90;
aldaketa=-5;
delay(1000);
do
{
//moverse
atzezk.run(FORWARD); // Hacia delante
atzesk.run(FORWARD);
auresk.run(FORWARD);
aurezk.run(FORWARD);
//Serial.println(encoderPos);
distancia=SONAR(angelua);
Serial.print("Neurtuta: ");
Serial.print(distancia);
minimoa=kalminimoa(angelua);
Serial.print(" DMIN: ");
Serial.println(minimoa);

 if(distancia90)
{
radianetan=angelua*(2*PI/360); 
minimo=(-7.5/cos(radianetan))+0.5; 

}
if (angelua==90)
{
 minimo=25; // 90º cos()-a error, 
}

// limitar la distancia mínima 
if (minimo>25)
{
 minimo=25;
}

 return minimo; 
}

En un código donde usas control de motores y dispositivos que deben captar "algo" para enviar una orden hay que hacer las cosas con mucha prolijidad aunque vaya a un sitio de internet y copie un código ese código no me asegura que está todo lo depurado que se requiere. Estoy escribiendo sin haberlo leído, cosa que haré ahora.

Me pongo a ver el programa y encuentro cosas primero en un idioma que no entiendo aunque traduje 2 o 3 sentencias no vale la pena el esfuerzo. Hazlo tu.

Bueno, evidentemente el código tiene muchos delay() o sea tiempos perdidos, y tiene loops como ese

do {} while(encoderPos<=405);

y me quedo corto... me encuentro que las indicaciones del Pixy conducen a cosas como esta

void Abat()
{
 JATORRItikAP();
 BIRAKETA();
 APtikA1();
 delay(5000); // Itxaroteko, gero kamara bidez objeturik ez dagoenenan gertatuko da.
 KONTRABIRAKETA();
 APtikA1();
 BIRAKETA2();
 JATORRItikAP();
 KONTRABIRAKETA();
}

donde no solo cada uno tiene loop con delays de 1000 mseg sino que en el medio tienes otro delay() de 5 segundos. Todo estos son los tiempos a los que me refería.

Si no lo sabías delay() es una instrucción que DESTRUYE un programa como el tuyo donde esperas la acción de otros sensores Pixy, ultrasónico, etc.

Delay() solo sirve cuando la tarea es secuencial al punto que no importa si me detengo o no a hacer algo.

Entiendo lo que dices, pero el programa entra sin ningún problema a la subrutina del sonar donde hace el calculo. Ahi no hay delays, mas que los de la salida del Trigger. Una vez ahi dentro los demás delay tienen repercusión?

En vez de usar un delay() recomendarias el uso de millis()??

Muchas gracias

Unai

Pon el código en "etiquetas de código", y los comentarios en español o inglés.

¿Que es un pixy2?

ElEspanol: Pon el código en "etiquetas de código", y los comentarios en español o inglés.

¿Que es un pixy2?

Ya he puesto el código con los comentarios en castellano, no me habia dado cuenta lo siento.

Pixy2 es una cámara que te permite obtener información de manera sencilla mediante vision artificial.

Me he mirado por encima lo que es pixy2 cam.

Sin haber analizado la programación del pixy, diría que podría ser un conflicto con los timer que usa el pulseIn().

Tiene sentido, porque el dato recogido de esa función es 0. Y no deberia. Como se puede contar el tiempo de otra forma?

timers de pulsein? Que yo sepa usa millis() entre flancos o estados de un pin o peor ciclos de reloj de instrucciones determinadas.

Este es el pulsein del IDE 1.0 ha pasado mucha agua bajo el puente pero todos los comentarios indican que trabaja mas o menos igual, no usa timers ni millis() como yo suponía

/*
  wiring_pulse.c - pulseIn() function
  Part of Arduino - http://www.arduino.cc/

  Copyright (c) 2005-2006 David A. Mellis

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General
  Public License along with this library; if not, write to the
  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  Boston, MA  02111-1307  USA

  $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
*/

#include "wiring_private.h"
#include "pins_arduino.h"

/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH
* or LOW, the type of pulse to measure.  Works on pulses from 2-3 microseconds
* to 3 minutes in length, but must be called at least a few dozen microseconds
* before the start of the pulse. */
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout)
{
 // cache the port and bit of the pin in order to speed up the
 // pulse width measuring loop and achieve finer resolution.  calling
 // digitalRead() instead yields much coarser resolution.
 uint8_t bit = digitalPinToBitMask(pin);
 uint8_t port = digitalPinToPort(pin);
 uint8_t stateMask = (state ? bit : 0);
 unsigned long width = 0; // keep initialization out of time critical area

 // convert the timeout from microseconds to a number of times through
 // the initial loop; it takes 16 clock cycles per iteration.
 unsigned long numloops = 0;
 unsigned long maxloops = microsecondsToClockCycles(timeout) / 16;

 // wait for any previous pulse to end
 while ((*portInputRegister(port) & bit) == stateMask)
 if (numloops++ == maxloops)
 return 0;

 // wait for the pulse to start
 while ((*portInputRegister(port) & bit) != stateMask)
 if (numloops++ == maxloops)
 return 0;

 // wait for the pulse to stop
 while ((*portInputRegister(port) & bit) == stateMask) {
 if (numloops++ == maxloops)
 return 0;
 width++;
 }

 // convert the reading to microseconds. The loop has been determined
 // to be 20 clock cycles long and have about 16 clocks between the edge
 // and the start of the loop. There will be some error introduced by
 // the interrupt handlers.
 return clockCyclesToMicroseconds(width * 21 + 16);
}

O sea es algo poco preciso. Usas micros() y tendras mejor precisión ni hablar con Timers.

Entonces me recomiendas quitar todos los delay() del codigo como digiste antes verdad?

Con el tema del pulsein? Recomiendas quitarlo y poner otra opcion?

Muchas gracias

Tienes para mi mucho trabajo Empieza con pixy que ya esta y no tienes mucha opción. Okay pixy llama a 1 de 3 rutinas

Yo comencé con tu código y luego vi que es para un buen rato y lo dejé

esto hice

void loop() {
  Serial.println("ITXAROTEN");
  pixy.ccc.getBlocks();     //Lee los datos de la cámara
  
  if (pixy.ccc.numBlocks) { // Averigua si se ha detectado algo
      while(pixy.ccc.blocks[0].m_signature) {
          case 1: Abat();  // Ir a un lugar
                  break;
          case 2: Abi();   Ir a dos lugares
                  break;
          case 3: digitalWrite(30,HIGH);
                  break;  
      }
  }
}

Ahora hay que trabajar con Abat() y Abi()

Haciendolos mas veloces.. cómo, usando millis() y creando máquina de estados.

Tu crees que haciendo Abat y Abi mas veloces la medicion del sonar ya no sera nula?

Porque antes con el mismo programa pero eligiendo el sitio al que ir a mano, sin la cámara, funcionaba bien, teniendo en cuenta todos los delays.

Yo creia que era mas la relación entre la Pixy2 y el sonar por eso pensaba que el tema del pulsein tendría sentido. Ya que la duración recibida del echo es 0.

Tu crees que haciendo Abat y Abi mas veloces la medicion del sonar ya no sera nula?

No claro que no. Una cosa no tiene que ver con la otra. Yo me alarmo por el código en general, no por la rutina del ultrasónico.

A ver si podemos trabajar de un modo sistemático, de lo contrario desde acá se hace dificil aconsejarte al menos para mi.

En procedimiento o rutina void JATORRItikAP() tienes este llamado al sonar.

distancia = SONAR(angelua);
  Serial.print("Neurtuta: ");
  Serial.print(distancia);

Funciona?

Establece por favor en cada caso si lo hace o no.

Como has tomado códigos de uno y otro lado, pixy descartemos porque sabemos que esta bien pero el otro código en lo personal me resulta complicado de seguir.

Entonces empecemos de nuevo si me permites la sugerencia porque con este código yo no voy a aconsejarte porque desde el comienzo al no poder entender o tener que traducir cada línea (tarea que te corresponde a ti si es que lo entiendes) prefiero comenzar por otro lado.

Tenemos un ROVER que tiene una camara pixy que detecta objetos, un sonar que le dirá cuando deterse luego que un objeto es identificado. Y claro el movimiento adelante, atras, izquierda, derecha y stop. Esto ultimo esta hecho muchas veces y como ahi es donde veo estan los problemas es que prefiero rehacer las cosas con ALGO entendible.

Espero tu comentario.

Si estas de acuerdo, te propongo que hagas un detalle aunque se lee en el código de como son las conexiones a tus drivers. Solo para que el novato que lea esto lo entienda mejor. Y de paso lo explicas un poco.

La llamada al sonar esta bien, entra en su subrutina. El problema es que da lectura 0. En el momento de realizar duracion=pulseIn ese resultado es 0. La variable duración da 0. Pero las llamadas y todos los demas movimientos que reaiza con los motores funcionan bien.

El único problema es que al conectar la camara Pixy2 la lectura obtenida desde el pulseIn es 0. Y por eso luego al compararlo con la distancia mínima se para. Porque cree que hay un objeto.

He estado indagando por internet y creo que se podria probar a crear una funcion que haga lo mismo que pulseIn mediante digitalWrite y micro(). Como lo ves? Podria llegar a funcionar?

Perdona por mi respuesta pero parece que no lees lo que he escrito antes.

O sea es algo poco preciso. Usas micros() y tendras mejor precisión ni hablar con Timers.

Tanto ELEspanol como yo te dijismos como hacerlo. Ahora. Solo estas reinventando la rueda. Existen librerías para manejar el sensor que obviamente desconoces.

NewPing es la librería mas usada pero hay otras.

Obviamente leo lo que escribís. ElEspañol me hizo pensar en que el problema esta ahi. Pero solo preguntaba que si se podia sustituirlo por un digitalwrite.

Por otro lado, si que conocia newping pero preferí hacerlo sin librerías. Es mas preciso hacerlo con la NewPing y crees que asi funcionaria?

Porque no te autorespondes probando con NewPing y vemos que resulta?

Porqué en la rutina del sonar mueves el servo?

long SONAR( int angelua) // Subrutina del sonar
{ 

   servoMotor.attach(10);         // <== Porque lo defines a cada momento?
   long duracion, distancia ;
   
   servoMotor.write(angelua);   // <== esto no debería estar acá y lo anterior menos
   delay(50);
   digitalWrite(52,HIGH);
   digitalWrite(trigPin, LOW);        // Nos aseguramos de que el trigger está desactivado
   delayMicroseconds(2);              // Para asegurarnos de que el trigger esta LOW
   digitalWrite(trigPin, HIGH);       // Activamos el pulso de salida
   delayMicroseconds(10);             // Esperamos 10µs. El pulso sigue active este tiempo
   digitalWrite(trigPin, LOW);        // Cortamos el pulso y a esperar el echo
   duracion = pulseIn(echoPin, HIGH) ;
   distancia = duracion / 2 / 29.1  ;
   //Serial.println(String(distancia) + " cm.") ;

   return distancia;
}

Observa los comentarios que hago para el servo.

Yo también uso newping.h, que yo sepa no bloquea o al menos tiene un timeout muy corto, porque puedes indicar una distancia máxima.

Vale, mañana probare a usar el NewPing. No lo he hecho antes porque hasta mañana no tengo acceso al material. Por eso preguntaba...

Lo del servo lo hago cada vez que entra para que vaya al angulo deseado que se quiere analizar la distancia. Cierto es que la definición no deberia estar ahi y que lo otro se puede poner en otro sitio.