# pulseIn Function - Version 0.1 (Beta)

**URL:** <https://community.particle.io/t/pulsein-function-version-0-1-beta/2276>\
**Category:** Firmware\
**Created:** [January 22, 2014, 12:14pm UTC](https://community.particle.io/t/pulsein-function-version-0-1-beta/2276 "2014-01-22T12:14:04Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![timb](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/timb/32/1913_2.png) [@timb](https://community.particle.io/u/timb)\
**Post date:** [January 22, 2014, 12:14pm UTC](https://community.particle.io/t/pulsein-function-version-0-1-beta/2276/1 "2014-01-22T12:14:04Z")

</div>

\*\*Current Version: 0.1.1 (Beta) _01/23/2014_ \*\*  
**Previous Version: 0.1 (Beta)**

Here’s my first real version of a _pulseIn()_ function for the Spark Core. Due to the blocking nature of this function, it has an intentional timeout of _10 seconds_ to prevent the WLAN from disconnecting. (That 10 seconds includes the time waiting for the pulse to trigger _and_ the actual pulse length.) Therefor this function currently has a useable range from about _10uS_ to _10S_! It’s accurate to _one microsecond_ at the low end of the scale.

To use this function, simply copy/paste the code (below) into your sketch (after the closing _brace_ [`}`] of `void loop()`) then call it just as you would any function.

`pulseIn(PIN, STATE);`  
`PIN: The pin to monitor for the pulse. [D0~D7|A0~A7]`  
`STATE: The state in which to start timing the pulse. [HIGH|LOW]`  
**Note: Make sure the pin has already been called with `pinMode(PIN, INPUT);` prior to calling this function, or it will fail.**

> <https://github.com/timothybrown/Spark-Core-Sundries/blob/master/function_pulseIn.cpp>

I still have a small list of things to add and tweak, but I’m really pleased with this initial release! Changing `digitalRead` to the low-level `GPIO_ReadInputDataBit` took the _while loop_ runtime down from 2.36uS to just 0.405uS!

So please, play with it, see how it works and give me your feedback! Like I said, I’ve already got a short todo list which I’ll work on over the rest of the week (I’ll post said list this afternoon). Hopefully by this weekend I can have a semi-final version ready for testing, if that goes well I’ll integrate the function into _spark\_wiring.cpp_ and submit a pull request. 😃

---

<div class="post-metadata">

**Author:** ![timb](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/timb/32/1913_2.png) [@timb](https://community.particle.io/u/timb)\
**Post date:** [January 22, 2014, 1:24pm UTC](https://community.particle.io/t/pulsein-function-version-0-1-beta/2276/2 "2014-01-22T13:24:46Z")

</div>

Thought I’d share some pictures of my testing setup, plus the code I used!

![](https://sea2.discourse-cdn.com/flex026/uploads/particle/326/19888883a301b1bf.jpg)  
**I set D4 as an INPUT and hooked it to the output of my AFG; D5 was set as an OUTPUT and connected to the AFG’s trigger input. Both of these connections were also routed to two analog inputs on my Scope.**

![](https://sea2.discourse-cdn.com/flex026/uploads/particle/327/9ebc210d66926985.jpg)  
**Here’s a nice view of the Core and gear during testing.**

![](http://img.timb.us/TEKMSO_01.png)  
**The trigger pulse from the Core captured by the Scope. It should be 1mS but is almost 40% too short. On a positive note, the digital output from the Core doesn’t overshoot much and contains very little noise!**

![](http://img.timb.us/TEKAFG_01.png)  
**AFG setup to send a 25mS pulse 5mS after being triggered.**

![](http://img.timb.us/TEKAFG_02.png)  
**Another setup for a 500uS pulse.**

```
int i = 0;
int disPos = 0;
void setup() {
    Wire.begin();
    pinMode(D4, INPUT);
    pinMode(D5, OUTPUT);
    pinMode(D6, OUTPUT);
    digitalWrite(D5, LOW);
    digitalWrite(D6, LOW);
}

void loop() {
    
    digitalWrite(D5, HIGH);
    delay(1);
    digitalWrite(D5, LOW);
    
    unsigned long pulseVal = pulseIn(D4, HIGH);
    unsigned long pulseRaw = pulseVal / 0.405;
    
    Wire.beginTransmission(0x4E);
    if (disPos == 0) {
        Wire.print("CL");
        disPos++;
    }
    else if (disPos == 5) {
        Wire.print("TP");
        Wire.write(0);
        Wire.write(0);
        disPos = 1;
    }
    else {
        Wire.print("TRT");
        disPos++;
    }
    Wire.print("TT");
    Wire.print(pulseVal);
    Wire.print(" / ");
    Wire.print(pulseRaw);
    Wire.write(0x00);
    Wire.endTransmission();
    delay(1000);
}

unsigned long pulseIn(uint16_t pin, uint8_t state) {
    
    GPIO_TypeDef* portMask = (PIN_MAP[pin].gpio_peripheral);
    uint16_t pinMask = (PIN_MAP[pin].gpio_pin);
    unsigned long pulseCount = 0;
    unsigned long loopCount = 0;
    unsigned long loopMax = 25000000;
    
    // While the pin is *not* in the target state we make sure the timeout hasn't been reached.
    while (GPIO_ReadInputDataBit(portMask, pinMask) != state) {
        if (loopCount++ == loopMax) {
            return 0;
        }
    }
    
    // When the pin *is* in the target state we bump the counter while still keeping track of the timeout.
    while (GPIO_ReadInputDataBit(portMask, pinMask) == state) {
        if (loopCount++ == loopMax) {
            return 0;
        }
        pulseCount++;
    }
    
    // Return the pulse time in microsecond!
    return pulseCount * 0.405; // Calculated the pulseCount++ loop to be about 0.405uS in length.
}

```

**Finally, here’s the code I used for testing. In a nutshell, it fires off a 1mS trigger pulse to the AFG on D5 then runs the pulseIn function on D4 to measure a precisely timed return pulse from the AFG. At this stage the pulseIn function was only returning the number of times pulseCount++ ran in the while loop. It would then print this out as a new line (or wrap to the top) on my OLED display before delaying for one second and starting the whole process over again.**

**So now, I could setup my AFG to output a pulse (e.g., 500uS) then read the pulseCount++ result on the OLED and by using some simple math determine the amount of time (in microseconds) that one loop took to run.**

**I then slightly modified the code to display both the raw pulseCount _and_ the microsecond output, so I could tweak the modifier a bit.**

That’s pretty much it! Surprisingly this took me almost all night, mainly because I tried reading the input port register another way at first, which ended up being a dead end. Once I got to the point of using the AFG to send precisely timed pulses to the Core, it only took me about two hours to get things tweaked and optimized (and a lot of that was waiting for the core to update OTA, since I was using my iPad in the lab).

---

<div class="post-metadata">

**Author:** ![chuck7](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/chuck7/32/20963_2.png) [@chuck7](https://community.particle.io/u/chuck7)\
**Post date:** [January 23, 2014, 4:19am UTC](https://community.particle.io/t/pulsein-function-version-0-1-beta/2276/3 "2014-01-23T04:19:26Z")

</div>

Worked great for me, with a (much) simpler setup - thanks!

![](https://sea2.discourse-cdn.com/flex026/uploads/particle/350/22a5749205bec333.jpg)

---

<div class="post-metadata">

**Author:** ![timb](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/timb/32/1913_2.png) [@timb](https://community.particle.io/u/timb)\
**Post date:** [January 23, 2014, 4:50am UTC](https://community.particle.io/t/pulsein-function-version-0-1-beta/2276/4 "2014-01-23T04:50:47Z")

</div>

Awesome! Glad to see it’s working well for you. That’s a very clean breadboard layout, I must say!

Make sure you guys subscribe to my Github feed _or_ this thread to try out the future updates and get notified when it gets submitted and goes live to the Core Build system. 😄

---

<div class="post-metadata">

**Author:** ![timb](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/timb/32/1913_2.png) [@timb](https://community.particle.io/u/timb)\
**Post date:** [January 23, 2014, 5:50am UTC](https://community.particle.io/t/pulsein-function-version-0-1-beta/2276/5 "2014-01-23T05:50:25Z")

</div>

I just hooked it back up to my ultrasonic sensor to start working on the Digole Display Library, and it seems to be working great! The output is pretty precise, too. 😄

![](https://sea2.discourse-cdn.com/flex026/uploads/particle/351/eca6b5c64bfac029.jpg)

---

<div class="post-metadata">

**Author:** ![BDub](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/bdub/32/5137_2.png) [@BDub](https://community.particle.io/u/BDub)\
**Post date:** [January 23, 2014, 6:37am UTC](https://community.particle.io/t/pulsein-function-version-0-1-beta/2276/6 "2014-01-23T06:37:46Z")

</div>

@timb I was doing a little Fast Reading tonight. If you want to put the pedal down all the way, check it out:  
[https://gist.github.com/technobly/8573877](https://gist.github.com/technobly/8573877)

---

<div class="post-metadata">

**Author:** ![timb](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/timb/32/1913_2.png) [@timb](https://community.particle.io/u/timb)\
**Post date:** [January 23, 2014, 7:32am UTC](https://community.particle.io/t/pulsein-function-version-0-1-beta/2276/7 "2014-01-23T07:32:21Z")

</div>

@BDub Cool! Direct port manipulation is fast as shit, isn’t it? 😃

Yeah, you know I went down that exact same road, however I couldn’t get `PIN_MAP[pin].gpio_peripheral->IDR & PIN_MAP[pin].gpio_pin` to compare to my _state variable_ in the _else loop_.

I.e.,

```
GPIO_TypeDef* portMask = (PIN_MAP[pin].gpio_peripheral);
uint16_t pinMask = (PIN_MAP[pin].gpio_pin);

while (portMask->IDR & pinMask) == state) {
	if (loopCount++ == loopMax) {
		return 0;
	}
	pulseCount++;
}

```

I tried masking the _state_ variable several ways and just as is, but despite the pin being high it would always return a _0_. (For debugging I even tried just monitoring the pin with similar code and printing the result of `portMask->IDR & pinMask` directly to my OLED.)

I was getting pretty tired there later on, so perhaps I screwed something up? Right now the loop is at 405nS, which gives under half a microsecond resolution, which I think is pretty damn good considering. My ultimate goal with this is to eventually buff up the _micros_ function using some assembly so it can act as an actual timer without overflowing every 7 minutes. Once this is done we can just use it to directly time the pulse length. This way the timing won’t be dependent on knowing the amount of time it takes for a particular loop to run (as in my current implementation) which will be very unreliable once the Spark Team moves all the background stuff into a separate concurrent loop.

Out of curiosity, how did you measure the timing in your Gist?

---

<div class="post-metadata">

**Author:** ![BDub](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/bdub/32/5137_2.png) [@BDub](https://community.particle.io/u/BDub)\
**Post date:** [January 23, 2014, 3:13pm UTC](https://community.particle.io/t/pulsein-function-version-0-1-beta/2276/8 "2014-01-23T15:13:08Z")

</div>

Agreed, we are coding for fun here… making it work, for now. Along the way, helping to uncover issues, and finding solutions to current problems.

The problem with `portMask->IDR & pinMask` is that the result is not always 0 or 1. It’s more like 0 or 0x0080 or 0x0040 or 0x0020. We haven’t bit shifted the port pin down to bit 0. That would take too much time anyway, so with just a tiny bit more code, we can have super speed:

```
unsigned long pulseIn(uint16_t pin, uint8_t state) {

    GPIO_TypeDef* portMask = (PIN_MAP[pin].gpio_peripheral);
    uint16_t pinMask = (PIN_MAP[pin].gpio_pin);
    unsigned long pulseCount = 0;
    unsigned long loopCount = 0;
    unsigned long loopMax = 25000000;

    if(state == HIGH) {
        // While the pin is *not* in the target state we make sure the timeout hasn't been reached.
        while ((portMask->IDR & pinMask) == 0) { // while the bit in the portmask is low
            if (loopCount++ == loopMax) {
                return 0;
            }
        }

        // When the pin *is* in the target state we bump the counter while still keeping track of the timeout.
        while (portMask->IDR & pinMask) { // while the bit in the portmask is high, might be 0x0080, 0x0040, etc..
            if (loopCount++ == loopMax) {
                return 0;
            }
            pulseCount++;
        }
    }
    else {
        // While the pin is *not* in the target state we make sure the timeout hasn't been reached.
        while (portMask->IDR & pinMask) { // while the bit in the portmask is high, might be 0x0080, 0x0040, etc..
            if (loopCount++ == loopMax) {
                return 0;
            }
        }

        // When the pin *is* in the target state we bump the counter while still keeping track of the timeout.
        while ((portMask->IDR & pinMask) == 0) { // while the bit in the portmask is low
            if (loopCount++ == loopMax) {
                return 0;
            }
            pulseCount++;
        }
    }
    
    // Return the pulse time in microsecond!
    return pulseCount * 0.405; // Calculated the pulseCount++ loop to be about 0.405uS in length.
}

```

I agree there are probably 15 other ways to do this with timers, capture compare inputs, interrupts… so for now it’s just fun to play around and think of different ways.

I measured the timing with my Rigol DS1053e. I will say that I took some liberties with claiming the timing… based on how you structure your code, the compiler and/or the GPIO bus seems to be delayed or sped up slightly based on what’s going on. So you should probably check the timing of the loop after calculating the K factor from 1us up to 1s. Hopefully it averages out to some number that works with a straight gain correction over the entire range.

---

<div class="post-metadata">

**Author:** ![Rockvole](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/rockvole/32/20733_2.png) [@Rockvole](https://community.particle.io/u/Rockvole)\
**Post date:** [September 30, 2014, 10:13pm UTC](https://community.particle.io/t/pulsein-function-version-0-1-beta/2276/9 "2014-09-30T22:13:23Z")

</div>

Hi @timb  
I am trying to use your library, but I get an error.  
Im calling with :

```
float concentration = dust.getConcentration(pulseIn(D1, LOW), millis(), DUST_SAMPLE_INTERVAL_MS);

```

And I get the error :

```
function_pulseIn.o: In function `pulseIn(unsigned short, unsigned char)':
/spark/compile_server/shared/workspace/3_compile-server2/core-firmware/build/function_pulseIn.cpp:42: multiple definition of `pulseIn(unsigned short, unsigned char)'
firmware.o:/spark/compile_server/shared/workspace/3_compile-server2/core-firmware/build/function_pulseIn.cpp:42: first defined here
```

---

<div class="post-metadata">

**Author:** ![Rockvole](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/rockvole/32/20733_2.png) [@Rockvole](https://community.particle.io/u/Rockvole)\
**Post date:** [October 1, 2014, 3:16pm UTC](https://community.particle.io/t/pulsein-function-version-0-1-beta/2276/10 "2014-10-01T15:16:18Z")

</div>

The error I get looks to me like Spark have implemented the pulseIn function? Except when I dont include timb’s function I get an error like pulseIn function not found.

---

<div class="post-metadata">

**Author:** ![peekay123](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/peekay123/32/810_2.png) [@peekay123](https://community.particle.io/u/peekay123)\
**Post date:** [October 1, 2014, 3:26pm UTC](https://community.particle.io/t/pulsein-function-version-0-1-beta/2276/11 "2014-10-01T15:26:45Z")

</div>

@Rockvole, unfortunately I don’t believe @timb is active on this forum anymore. I will try and take a look at his code to see what the issue might be. How are you compile the code: IDE, CLI or locally? Can you post your code so I can get a better picture of how you are using @timb’s code?

---

<div class="post-metadata">

**Author:** ![Rockvole](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/rockvole/32/20733_2.png) [@Rockvole](https://community.particle.io/u/Rockvole)\
**Post date:** [October 1, 2014, 3:41pm UTC](https://community.particle.io/t/pulsein-function-version-0-1-beta/2276/12 "2014-10-01T15:41:24Z")

</div>

Hi @peekay123,  
Thanks for the response. I trimmed my code down to the minimum which causes the error :

```
#include "function_pulseIn.cpp"

void setup()
{
}

void loop() {
    pulseIn(D1, LOW);
}

```

I added #include \<application.h\>  
to the top of timb’s code :

> <https://github.com/timothybrown/Spark-Core-Sundries/blob/master/function_pulseIn.cpp>

---

<div class="post-metadata">

**Author:** ![peekay123](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/peekay123/32/810_2.png) [@peekay123](https://community.particle.io/u/peekay123)\
**Post date:** [October 1, 2014, 9:13pm UTC](https://community.particle.io/t/pulsein-function-version-0-1-beta/2276/13 "2014-10-01T21:13:52Z")

</div>

@Rockvole, doing an include of a .cpp file does not cause the proper pre-processing that a .h file normally gets. If you paste the actual code at the top of your app before setup() or rename `function_pulseIn.cpp` to `function_pulseIn.h` and change the #include, it will compile just fine. 😄

---

<div class="post-metadata">

**Author:** ![Rockvole](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/rockvole/32/20733_2.png) [@Rockvole](https://community.particle.io/u/Rockvole)\
**Post date:** [October 2, 2014, 2:35am UTC](https://community.particle.io/t/pulsein-function-version-0-1-beta/2276/14 "2014-10-02T02:35:16Z")

</div>

Thanks for the help @peekay123 - that compiles fine now.

Strange no-one improved that obtuse error during 35 years of C++ compilers 😄

---

<div class="post-metadata">

**Author:** ![tcb2](https://avatars.discourse-cdn.com/v4/letter/t/67e7ee/32.png) [@tcb2](https://community.particle.io/u/tcb2)\
**Post date:** [June 2, 2015, 8:02pm UTC](https://community.particle.io/t/pulsein-function-version-0-1-beta/2276/15 "2015-06-02T20:02:05Z")

</div>

the pulseIn code here works but if there is a time out, 10 seconds is long enough to disconnect the particle from the cloud, perhaps depending on what other delays you may have in your code. I have shortened by timeout counter (loopMax) to 1000000 and still get reasonable results.
