Non-pending pulseIn() function???

Hello:

I am looking to implement several ultrasonic sensors (3 to 5) and I cannot afford to wait on pulseIn() to return the time delay. In my implementation, the arena of interest to the robot is 12 x 8 feet. At 12 feet, the ultrasonic propagation time (out and back) is over 20ms. Is there a library, similar to Servo library, where non-pending equivalent to pulseIn() functions have been implemented?

Thanks for any suggestions or leads, -john

you should look into getting the sensors trigger an interrupt => think you should use the pinchangeinterrupt library to handle the receiving.

check - http://playground.arduino.cc/Main/PinChangeInt -

Rob:

Thanks for your fast reply. I will look into this library. I'm new to the Arduino platform and had not noticed this library. At first glance, I think I can integrate this into a densely packed service routine environment. -john (ServoHawk)

ServoHawk: Rob:

Thanks for your fast reply. I will look into this library. I'm new to the Arduino platform and had not noticed this library. At first glance, I think I can integrate this into a densely packed service routine environment. -john (ServoHawk)

Using pin interrupt is not a good method for ultrasonic sensors as sometimes you never get a ping echo and you end up waiting forever (worse than using pulseIn()).

Instead, consider using the NewPing library which is designed for multiple sensors. Successful projects have used the NewPing library with up to 15 sensors (and it can accommodate even more).

As a bonus, the author is SUPER cool to work with, offering tons of fast support ;-)

Tim

What exactly is a non-pending function?

I interpreted it as a non-blocking function (as pulseIn() is blocking)

dhenry: What exactly is a non-pending function?

pulseIn waits for up to a second to get the desired result. In a way, it can many times be like adding a delay(1000) right in the middle of your sketch. That may be fine for testing, but not really desirable for real-world applications. Consider trying to ping 15 sensors to control a fast moving robot. If it could take 15 seconds to ping all the sensors, it doesn't really help control the robot. Also, a lot can happen even in one second if only using one sensor.

That's why NewPing doesn't use pulseIn at all. Not even for the standard ping() method that doesn't use the timer interrupt.

Tim

Tim:

Thanks for the intro to your new library. Yup, I agree with all the shortcomings to the introductory approaches to Ping implementation. I'm looking forward to using your library. One project, several Ping devices on one platform. Another project, multiple LV-MaxSonar-EZ0 rangefinders (I have yet to field test these) on a 4mph companion (Wild Thumper) for my walks. Additional project, two IR-Beacon and Ping-sensing robots in cat&mouse scheme with simple mapping and utilization/avoidance of shields within their arena. A lot of projects bidding for my time... I will share success as these projects mature.

Thanks again for the fine lead, -john (ServoHawk)

One way to solve it would be to use millis()/micros() and at the time of pin state changes, recording the millis()/micros() reading. That can be done via interrupts (EINTx or PCINTx) or via polling (dumber way in my view).

#define PULSE_PIN  8
#define TIME()     millis()  //count to ms. use micros() to count to us

void pulse_init(void) {
  pinMode(PULSE_PIN, INPUT);
}

unsigned char pulse_count(unsigned long *p_count) {
  static unsigned char pin_prev=0; //previous state of the pin
  static unsigned long start_time = TIME();
  unsigned long time;
  unsigned char tmp=digitalRead(PULSE_PIN);
  
  if (tmp ^ pin_prev) {  //pin state has changed
    time = TIME();       //record current time
    pin_prev = tmp;    //save the pin state
    if (start_time) {    //already in a counting session now
      *p_count = time - start_time;  //calculate time elapsed
      start_time=0;      //indicating end of a counting session
      return 1;          //we have new data
    } else {             //start of a counting session
      start_time = time; //record the start time
      return 0;          //no count yet
    }
  } else {               //pin state has not changed
    return 0;            //no new count
  }
}


void setup(void)  {
  Serial.begin(9600);
  pulse_init();            //initialize the module
}

unsigned long count;
void loop(void)  {
  if (pulse_count(&count)) {  //new data has arrived
    Serial.print("Count = "); Serial.print(count); Serial.println("ms.");
  }
  
}

Here pulse_count() returns 1 if new count data is available. Otherwise, 0.

The ultimate approach would be to use the timer capture feature.