This Arduino topic is an over-simplification and not very robust, but it presents in code the basic principle of threshold detection and the subtraction of adjacent pulse times (period). BPM = 60.0 / period in seconds.
If you want something that would work under a larger range of conditions, you can add the three primary missing features used by medical instrumentation.
- Automated zeroing, which can be accomplished with an analog filter and pull-up or with a digital high pass filter that attenuates frequencies below 0.3 Hz. This can be done with a series capacitor leading to the analog input being sampled, with a pull up resistor to V+ and another resistor to ground to center the Voltage to an appropriate positive steady state value.
- Attenuation of frequencies above those representing a pulse to avoid false triggers from high frequency noise, cross-talk, or transients, which can be accomplished with an analog filter or with a higher sample rate and a digital low pass filter that attenuates frequencies above 100 Hz 1.
- Dynamic range compression, which detects the trend in pulse amplitude and continuously adapts the trigger threshold accordingly to avoid false indication of beats or the missing of weaker but legitimate beats.
To do the filtering digitally, you may want to read up on DSP (digital signal processing). There are several great books on it, and you can search for simple algorithms for both low pass filters and high pass filters in GitHub or elsewhere in the open source community.
[1] Wikipedia's article on low pass filters