Dos o más sensores de ultrasonido juntos?

Hola, estoy intentando montar en una sola placa de Arduino UNO varios sensores de ultrasonidos HC-SR04 apuntados en distintas direcciones de manera que si la distancia baja de 50 cm (aprox.) en alguno de los sensores, se encienda un led de color. Cada sensor de ultrasonido tiene asignado un led distinto para saber cual de los sensores ha detectado la proximidad.
Lo he montado con un único sensor y un led y funciona perfecto con este sketch:

long distancia1;
long tiempo1;
int speaker = 5;
int green = 13;

void setup() {
  Serial.begin(9600);
  pinMode(9, OUTPUT); /*activación del pin 9 como salida: para el pulso ultrasónico*/
  pinMode(8, INPUT); /*activación del pin 8 como entrada: tiempo del rebote del ultrasonido*/
  pinMode (green, OUTPUT); /*led*/
  pinMode (speaker, OUTPUT);
}

void loop() {
  digitalWrite(9, LOW); /* Por cuestión de estabilización del sensor*/
  delayMicroseconds(2);
  digitalWrite(9, HIGH); /* envío del pulso ultrasónico*/
  delayMicroseconds(5);

  tiempo1 = pulseIn(8, HIGH); /* Función para medir la longitud del pulso entrante*/
  distancia1 = int(0.017 * tiempo1); /*fórmula para calcular la distancia obteniendo un valor entero*/

  if (tiempo1 < 4000) {
    digitalWrite(green, HIGH);
    digitalWrite(speaker, HIGH);
  }
  else {
    digitalWrite(green, LOW);
    digitalWrite(speaker,LOW);
  }

  /*Monitorización en centímetros por el monitor serial*/
  Serial.println("Distancia 1 ");
  Serial.println(distancia1);
  Serial.println("cm");
  Serial.println(tiempo1);


  delay(200);

}

El problema viene cuando intento añadir otro sensor. Lo que hago es conectar todos los "Trig" al Pin 9, y el "Echo" de cada sensor a un pin distinto. Luego añado una condición "if" para el segundo sensor, exactamente igual que para el primero. Pero por algún motivo el segundo sensor no funciona nada de nada. En el serial me da valor 0 constante, y ademas el primer sensor empieza a funcionar mal, con retrasos de varios segundos entre detectar el objeto y encender o apagar el led... hay alguna forma de, en un solo "if" incluir todos los sensores?

Gracias!

¿Has probado a usar la librería "New Ping"? Funciona muy bien.

http://playground.arduino.cc/Code/NewPing

No la tenia vista! Tiene muy buena pinta, voy a adaptarlo para funcionar con ella. Estaba intentando lo mismo con la librería "Ultrasonic" y he conseguido que varios sensores me tomen lecturas correctas a la vez, el problema es que no se como asignar un led distinto a cada sensor, ya que al trabajar con librería no se definirlo.

Por otro lado...alguien sabría decirme si con una sola función puedo hacer que cada led se encienda o apague dependiendo de si el sensor al que esta asociado detecta un objeto o no? Puedo hacer una función "if" para cada sensor y cada led (como en el sketch que he colgado antes) pero me ocupa mucho espacio y estoy casi seguro de que debe haber alguna formula para juntarlo en una sola función general... pero de nuevo, al trabajar con librería no se por donde empezar.

Gracias!

1 Like

En principio nada te impide hacer eso, yo lo he hecho con varios termistores para jugar y debería ser parecido. Lo que yo no sé es si va a haber problemas con un sensor detectando al otro o cosas así, al margen de eso lo lógico es que deberías poder.
Un saludo.

Meiyus:
Por otro lado...alguien sabría decirme si con una sola función puedo hacer que cada led se encienda o apague dependiendo de si el sensor al que esta asociado detecta un objeto o no? Puedo hacer una función "if" para cada sensor y cada led (como en el sketch que he colgado antes) pero me ocupa mucho espacio y estoy casi seguro de que debe haber alguna formula para juntarlo en una sola función general... pero de nuevo, al trabajar con librería no se por donde empezar.

Respecto de las librerías piensa que antes de ponerte a hacer algo investiga todo lo referente a ese tema. Simple pones en google: Arduino ultrasónico o Arduino ultrasonico multiple y ya verás lo que obtienes.

Cada sensor te dará una lectura en distancia. Por lo que pretendes, deberás fijar umbrales para que entonces tomes control del led y lo prendas/apagues según corresponda.

Hay un ejemplo en NewPing que maneja varios sensores. Es un punto de partida.
Hazlo funcionar y luego seguimos.

1 Like

Buenas!

He conseguido que dos sensores me tomen lecturas correctas a la vez con la librería NewPing. El problema es que con la librería no se como incluir el comando "if" para asignar un led a cada sensor y que se encienda si su sensor detecta algo.
He buscado en google como hacerlo pero solo encuentro tutoriales de como crear o modificar librerias... nada sobre como hacer lo que quiero. Supongo que es algo tan básico que cualquiera que sepa programar sabe como hacerlo... pero yo no tengo ni idea.

Este es el sketch que me funciona. Es el que viene como ejemplo con la libreria para funcionar con 15 sensores, modificando el numero de sensores y el serial.begin:

#include <NewPing.h>

#define SONAR_NUM     2 // Number or sensors.
#define MAX_DISTANCE 200 // Maximum distance (in cm) to ping.
#define PING_INTERVAL 33 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo).

unsigned long pingTimer[SONAR_NUM]; // Holds the times when the next ping should happen for each sensor.
unsigned int cm[SONAR_NUM];         // Where the ping distances are stored.
uint8_t currentSensor = 0;          // Keeps track of which sensor is active.

NewPing sonar[SONAR_NUM] = {     // Sensor object array.
  NewPing(1, 2, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping.
  NewPing(4, 3, MAX_DISTANCE),
};

void setup() {
  Serial.begin(9600);
  pingTimer[0] = millis() + 75;           // First ping starts at 75ms, gives time for the Arduino to chill before starting.
  for (uint8_t i = 1; i < SONAR_NUM; i++) // Set the starting time for each sensor.
    pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL;
}

void loop() {
  for (uint8_t i = 0; i < SONAR_NUM; i++) { // Loop through all the sensors.
    if (millis() >= pingTimer[i]) {         // Is it this sensor's time to ping?
      pingTimer[i] += PING_INTERVAL * SONAR_NUM;  // Set next time this sensor will be pinged.
      if (i == 0 && currentSensor == SONAR_NUM - 1) oneSensorCycle(); // Sensor ping cycle complete, do something with the results.
      sonar[currentSensor].timer_stop();          // Make sure previous timer is canceled before starting a new ping (insurance).
      currentSensor = i;                          // Sensor being accessed.
      cm[currentSensor] = 0;                      // Make distance zero in case there's no ping echo for this sensor.
      sonar[currentSensor].ping_timer(echoCheck); // Do the ping (processing continues, interrupt will call echoCheck to look for echo).
    }
  }
  // The rest of your code would go here.
}

void echoCheck() { // If ping received, set the sensor distance to array.
  if (sonar[currentSensor].check_timer())
    cm[currentSensor] = sonar[currentSensor].ping_result / US_ROUNDTRIP_CM;
}

void oneSensorCycle() { // Sensor ping cycle complete, do something with the results.
  for (uint8_t i = 0; i < SONAR_NUM; i++) {
    Serial.print(i);
    Serial.print("=");
    Serial.print(cm[i]);
    Serial.print("cm ");
  }
  Serial.println();
}

¿Alguien me puede echar una mano?

A ver si esto soluciona parcialmente tu problema

Acá esta la comparación que buscas pero requiere de algunas definiciones previas.

unsigned int Umbral[SONAR_NUM]  = {50, 50}; // Ajusto dos umbrales en 50 cmt
const byte pinLed[SONAR_NUM]    = {8, 9};   // Supongo pin 8 y 9 para los leds

Umbral es un vector de tantos elementos como SONAR_NUM tenga. Obviamente como tu definiste 2, yo definí solo dos umbrales. Luego podrás modificar a la cantidad que quieras.

pinLed[] es el vector que dirige los leds.

 if (cm[currentSensor] > Umbral[currentSensor]) {   // supongo que quieres que encienda el led si supera los cmt para c/sensor
      digitalWrite(pinLed[currentSensor], HIGH);
    }
    else
      digitalWrite(pinLed[currentSensor], LOW);
  }
#include <NewPing.h>

#define SONAR_NUM     2 // Number or sensors.
#define MAX_DISTANCE 200 // Maximum distance (in cm) to ping.
#define PING_INTERVAL 33 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo).

unsigned long pingTimer[SONAR_NUM]; // Holds the times when the next ping should happen for each sensor.
unsigned int cm[SONAR_NUM];         // Where the ping distances are stored.
uint8_t currentSensor = 0;          // Keeps track of which sensor is active.

NewPing sonar[SONAR_NUM] = {     // Sensor object array.
  NewPing(1, 2, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping.
  NewPing(4, 3, MAX_DISTANCE),
};

unsigned int Umbral[SONAR_NUM]  = {50, 50}; // Ajusto dos umbrales en 50 cmt
const byte pinLed[SONAR_NUM]    = {8, 9};   // Supongo pin 8 y 9 para los leds

void setup() {
  Serial.begin(9600);
  pingTimer[0] = millis() + 75;           // First ping starts at 75ms, gives time for the Arduino to chill before starting.
  for (uint8_t i = 1; i < SONAR_NUM; i++) // Set the starting time for each sensor.
    pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL;
}

void loop() {
  for (uint8_t i = 0; i < SONAR_NUM; i++) { // Loop through all the sensors.
    if (millis() >= pingTimer[i]) {         // Is it this sensor's time to ping?
      pingTimer[i] += PING_INTERVAL * SONAR_NUM;  // Set next time this sensor will be pinged.
      if (i == 0 && currentSensor == SONAR_NUM - 1) oneSensorCycle(); // Sensor ping cycle complete, do something with the results.
      sonar[currentSensor].timer_stop();          // Make sure previous timer is canceled before starting a new ping (insurance).
      currentSensor = i;                          // Sensor being accessed.
      cm[currentSensor] = 0;                      // Make distance zero in case there's no ping echo for this sensor.
      sonar[currentSensor].ping_timer(echoCheck); // Do the ping (processing continues, interrupt will call echoCheck to look for echo).
    }
    if (cm[currentSensor] > Umbral[currentSensor]) {   // supongo que quieres que encienda el led si supera los cmt para c/sensor
      digitalWrite(pinLed[currentSensor], HIGH);
    }
    else
      digitalWrite(pinLed[currentSensor], LOW);
  }
  // The rest of your code would go here.
}

void echoCheck() { // If ping received, set the sensor distance to array.
  if (sonar[currentSensor].check_timer())
    cm[currentSensor] = sonar[currentSensor].ping_result / US_ROUNDTRIP_CM;
}

void oneSensorCycle() { // Sensor ping cycle complete, do something with the results.
  for (uint8_t i = 0; i < SONAR_NUM; i++) {
    Serial.print(i);
    Serial.print("=");
    Serial.print(cm[i]);
    Serial.print("cm ");
  }
  Serial.println();
}

Dime como resulta.

Hola surbyte. Muchas gracias por tu ayuda pero no consigo que funcione. Los leds parpadean constantemente a una velocidad increible, imagino que cada microsegundo que los sensores no mandan señal, los leds lo toman como una lectura menor del umbral o algo así. Además me he fijado y con la libreria NewPing los sensores toman lecturas contrarias, es decir, uno me mide la distancia maxima y se reduce cuando hay un objeto en medio, y el otro me toma distancia minima y la aumenta cuando detecta el objeto:

0cm  210cm
0cm  210cm
0cm  210cm
0cm  210cm
0cm  210cm
0cm  210cm
0cm  210cm

El sensor de la izquierda me da lectura 0 constante, y el de la derecha me da la distancia maxima a la pared, pero si introduzco el objeto delante de los sensores entonces los dos me dan la lectura correcta detectando el objeto.

32cm  32cm
32cm  32cm
32cm  32cm
32cm  32cm
32cm  32cm
32cm  32cm
32cm  32cm
32cm  32cm

El problema obvio es que uno de los leds esta siempre encendido, porque sin ningún obstaculo cerca siempre da lectura 0, por debajo del umbral.

Trabajar con la libreria NewPing me resulta muy complicado. La libreria Ultrasonic ( Libreria para Arduino del modulo Ultrasonic Ranging HC-SR04 | Ardublog ) es mucho más simple y creo que para lo que quiero hacer es suficiente. Pero al no definir los sensores en un array no se como asignar un led a cada sensor. Este es el sketch que me funciona para tomar lecturas con dos sensores ultrasonicos a la vez:

#include <Ultrasonic.h>

Ultrasonic ultraleft(1,2);   // (Trig PIN,Echo PIN)
Ultrasonic ultraright(3,4);  // (Trig PIN,Echo PIN)

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

void loop()
{
  Serial.print("Left: ");
  Serial.print(ultraleft.Ranging(CM)); // CM or INC
  Serial.print(" cm     " );
  delay(50);
  Serial.print("Right: ");
  Serial.print(ultraright.Ranging(CM)); // CM or INC
  Serial.println(" cm" );
  delay(50);
}

En este caso ¿puedo asignar un led a cada sensor y luego hacer un codigo "if" como el que me has mandado, con el vector [currentSensor]?

Buenas tardes, el problema se puede solucionar fácilmente con el siguiente código.
Fíjate en que solamente he añadido una función extra, utilizando el último código que has publicado.

Ultrasonic ultraleft(1, 2);  // (Trig PIN,Echo PIN)
Ultrasonic ultraright(3, 4); // (Trig PIN,Echo PIN)

int ledIzq = 5; // Pin del led izquierdo
int ledDer = 6; // Pin del led derecho
void setup() {
  Serial.begin(9600);
}

void loop()
{
  Serial.print("Left: ");
  Serial.print(ultraleft.Ranging(CM)); // CM or INC
  Serial.print(" cm     " );
  encenderLed(ultraleft.Ranging(CM), 50, ledIzq);
  delay(50);
  Serial.print("Right: ");
  Serial.print(ultraright.Ranging(CM)); // CM or INC
  encenderLed(ultraright.Ranging(CM), 50, ledDer);
  Serial.println(" cm" );
  delay(50);
}
void encenderLed(float cm, float umbral, int ledPin) {
  digitalWrite(ledPin, cm < umbral);
}

La función encenderLed toma los parámetros de distancia, umbral y el pin del led que deseas encender. Dentro de esta función se le ordena al led que se encienda si la distancia es menor a ese umbral o se apague si es menor en una sola línea de código.

Espero haberrte ayudado,
un saludo

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.