pulseIn not working correctly for Duemilanove

Hi,

This is my first post here, so please forgive me if I am being stupid.

It seems to me, unless I missing, something that the values I'm getting back from pulseIn are off by a couple of orders of magnitude.

I am posting the test code I've used, in which I simulate getting a pulse in by simply connecting a jumper from pin 12 to pin 7 for about 2 seconds (just counting in my head to measure 2 seconds). Below the code is the output.

void setup(){
 pinMode(7, INPUT);
 pinMode(12, OUTPUT);
 digitalWrite(12,HIGH);
 Serial.begin(9600);
}

void loop(){
 unsigned long duration;
 unsigned long start;
 unsigned long end;
 unsigned long elapse;
 delay(500);
 Serial.println("Reading pulse");
 start = micros();
 duration = pulseIn(7, HIGH, 2000000L);
 end = micros();
 elapse = end - start;
 Serial.print("Elapsed time: ");
 Serial.println(elapse);
 Serial.println(duration);
 delay(1500);
}

Output:

Reading pulse

Elapsed time: 2837972

249778345

Any help understanding this would be greatly appreciated. It looks to me like pulsIn is reporting the pulse having a duration of about 250 seconds, even though only 2.8 seconds have elapsed.

From http://arduino.cc/en/Reference/PulseIn :

"Returns the length of the pulse in microseconds." (emphasis mine)

Whereas, millis() returns milliseconds.

;)

!c

Ummm yeah, I knew that. But if you look at the code I am not comparing the return from pulseIn to mills... I'm comparing it to micros, so yes, there is still an error here.

pulseIn() Description

Reads a pulse (either HIGH or LOW) on a pin. For example, if value is HIGH, pulseIn() waits for the pin to go HIGH, starts timing, then waits for the pin to go LOW and stops timing. Returns the length of the pulse in microseconds. Gives up and returns 0 if no pulse starts within a specified time out.

start = micros();
 duration = pulseIn(7, HIGH, 2000000L);
 end = micros();

end-start = Total time from signal LOW to HIGH to LOW, so if the signal was low when you start pulseIn, it will wait until it gets HIGH before starting to count.

That information is all correct. However it in no way even comes close to explaining how the period of time (in microseconds) the pulseIn returned is almost 100 times longer than the period of time that elapsed (also in microseconds) from the start of the call to the end of the call.

I am not confused here because the length of time returned by pulseIn is not what I expected, I am confused because it is not actually possible for the value returned from pulseIn to be a reflection the period of time that it received a high pulse.

Well I'm far from being experianced with C and probably someone more experianced then me can give a better explaination, but I think you are not using pulsein function correctly.

Pulsein is a "blocking" instruction that prevents any other operation from being performed until it sees a proper transistion on it's input pin, from high to low to high or low to high to low, or if it sees no transistions it just times out if you provided a time-out value like you did. You are setting output pin high prior to the pulse in command but there is change of state for the pulse in command to see. You are setting output pin 12 high prior to pulsin but there is no way for output pin 12 to change states and create a pulse once you enter the pulse in command.

If you want to simulate a pulse why don't you do a PWM output pin set at 50% duty via analogwrite function and wire that PWM output pin to your pulsein input pin. The PWM output will continue to output pulses during out pulsin function and you should get the a reading equal to half of the PWM frequency.

Lefty

Sorry, got confused your two value started with "2...." i did not count the amount of digits, let me check some more and i will try to figure it out.

This is what i got after doing your setup?

Reading pulse

Elapsed time: 1863048

1467017

Reading pulse

Elapsed time: 2553328

1549895

Reading pulse

Elapsed time: 2104932

1486732

You are probably using arduino 0013 as i could not compile using 0012! i try this on a Atmega328 Seems to work fine! Did it did that once or all the time?

It has done that everytime I've attempted it.

I came to this experiment after playing with the ping example. With a set up identical to the one shown on the website, and the code directly from the website, I was getting measurements in inches that were impossibly wrong. I conducted this experiment to attempt to determine if the paralax png sensor was not working, or if i was just getting erroneous readings from pulseIn.

At this point my best guess, which I will be testing as soon as I can, is that it has to due with the environment on my laptop.

I am running arduino 0013, in ubuntu 8.10_x86 64 bit. I have followed some directions I found for getting the arduino environment to run on a 64 bit OS (using the Sun jvm, with a 32-bit compatibility pack installed), and before now, I'd never had a problem.

Reading pulse

Elapsed time: 2837972

249778345

I got similar values on my Diecimila on Windows XP. Tested it with 0013 (and 0014).

If you compare 0012 to 0013 then you see a difference: 0013 waits for any previous pulse to end while 0012 did not wait for this... at least that is what the svn sources suggest: http://code.google.com/p/arduino/source/browse/tags/0012/hardware/cores/arduino/wiring_pulse.c http://code.google.com/p/arduino/source/browse/tags/0013/hardware/cores/arduino/wiring_pulse.c

I will check my wires again when I am at home and try to make pin 7 an input with pullup and then wait for a LOW signal line using pulseIn.

So I can't explain the problem right now but I can confirm the values DaveMAA has posted.

Update:

I downloaded arduino 0012 (linux amd-64bit) version from http://www.arduino.cc/en/Main/Software...

Same problem, no change.

Another update:

In my frustration, I just decided to write my own version of pulseIn, rather than trying to figure out why pulseIn was not returning accurate results.

If anyone else is having this problem and would like to use this code, here it is. I tested my readPulse method in both my test program posted above, and the ping example from the arduino website, and in both cases it consitantly returns values within expected range. (Wanring: I have yet to test boundary cases and error conditions!)

unsigned long readPulse(int pin, int signal, unsigned long timeout){
  unsigned long current, killTime, ptime;
  current = micros();
  killTime = current + timeout;
  while(digitalRead(pin) == signal){
   delayMicroseconds(4); 
   current = micros();
    if(current >= killTime){
      return 0UL;
    }
  }
  while(digitalRead(pin) != signal){
   delayMicroseconds(4);
    current = micros(); 
    if(current >= killTime){
      return 0UL;
    }
  }
  ptime = micros();
  while(digitalRead(pin) == signal){
   delayMicroseconds(4); 
  }
  return micros() - ptime;
}

I will give it a try later. I wonder that the results are better, because you use digitalRead(pin)... this function takes a long time to actually read the pin value. That's why

*portInputRegister(port) & bit

is used instead in the pulseIn function...

can you post some numbers? How accurate is your solution?

I'll post some numbers in this post as soon as I get home tonight.

Given that my original goal was to get the ping example working with my parallax ultra sonic range finder, I can tell you that I got readings accurate to within a half inch with my test object ranging from 3 - 63 inches from the range finder.

I'm don't know how long the digitalRead function takes... However if one assumes that takes 0 micros to return (clearly not accurate), the pure logic in the code would indicate that it should be accurate within 8 microsecnds. I choose the "delayMicroseconds(4)" to throttle the while loops based on my understanding that the micros() function is only accurate to within 4 microseconds (leading me to believe that even the built in function pulseIn could not be accurate beyond a 4 microsecond resolution).

Given my goal here... if the function is accurate even only to within 28 microseconds, the distance reading from a range finder should still be accurate to within a quarter of an inch (assuming the png sensor itself is perfect), which is more than accurate enough for my purposes.

DaveMAA: what version of avr-gcc do you have? I.e. what do you get if you run:

avr-gcc --version

on the command line? There are apparently some versions (4.3.0) that have problems with multiplication of certain types, which could be causing the strangeness you're seeing.

Ahh soo...

Wise Mellis. I do in fact have avr-cc 4.3.0. I will look to upgrade or down grade now to see if the problem is resolved.

Thank you much for your assistance.

Well, I have made progress. It took a few attempts, and a few hours resolving a web of dependencies to get the newer version of avr-gcc, avrdude and libusb all talking to one another happily.

At this point I can upload code to the arduino, but the IDE crashes as soon as I try to bring up the serial monitor. Still working it, but any pointers would be appreciated.

Hi, I have the same extrange problem.

Arduino12 and arduino15 on Ubuntu Intrepid.

Here is my post ...

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1240684825/0

Any idea ??

DaveMAA,

Thanks for posting the code, readPulse. I have spent a few hours "troubleshooting" strange output from the Memsic 2125. Turns out the output was fine, the pulseIn function is acting strange. Even bought a new 'scope! (OK, my old ones were crap and the modern Teks are so cool).

Something is wrong with the Arduino_0015 codebase and the Duemilanove Atmega328 support it seems. There are rumblings of it elsewhere. I would post, but this is my first and linking is not allowed. Searching for:

AVR header messed up for 328

and

pulseIn( pin, LOW ) returns huge wrong values

might help.

Hopefully 0016 will be fixed...

Dave

hartze11: what operating system are you on? Which version of avr-gcc do you have? (avr-gcc --version).