initial commit
initial commit

--- /dev/null
+++ b/UltrasonicSensor/UltrasonicSensor.ino
@@ -1,1 +1,104 @@
+/**
+* @author Razvan Stanga
+* 
+*
+* Example sketch for working with the HC-SR04 Ultrasound distance sensor
+* http://users.ece.utexas.edu/~valvano/Datasheets/HCSR04b.pdf
+*
+* based on Mike Almond - @mikedotalmond  https://github.com/mikedotalmond/arduino-pulseInWithoutDelay
+* Uses a hardware interrupt to monitor the echo pin and measure the pulse length (without pausing code execution like you would when using Arduino::pulseIn())
+*
+* See http://arduino.cc/en/Reference/AttachInterrupt for more on the Arduino hardware interrupts
+*
+* Use these interrupt pins for your board
+* Board	            int.0	int.1	int.2	int.3	int.4	int.5
+* Uno, Ethernet,Mini	2	3
+* Mega2560	        2	3	21	20	19	18
+* Leonardo, Micro	3	2	0	1
+*
+**/
 
+#include <UltrasonicInterrupt.h>
+
+const float SpeedOfSound     	= 343.2; // ~speed of sound (m/s) in air, at 20°C
+const float MicrosecondsPerMillimetre 	= 1000.0 / SpeedOfSound; // microseconds per millimetre - sound travels 1 mm in ~2.9us
+
+const float  MicrosecondsToMillimetres  = (1.0 / MicrosecondsPerMillimetre);
+const float  MicrosecondsToMillimetres2 = MicrosecondsToMillimetres / 2.0; // beam travels the distance twice... so halve the time.
+
+const int SIGNAL_PIN	= 2; 	// digital pin connected to the trigger port on the module 
+                                // connect the echo port to the pin for interrupt 0 (pin 2 on Uno) 
+const int INTERRUPT_PIN  = 2;  // custom interrupt pin, see above
+
+unsigned long lastTime	= 0;
+
+int pingTimer			= 0;
+int pingDelay			= 500; // milliseconds between ping pulses
+
+float millimetres 		= 0.0;
+
+
+void setup() {
+
+  Serial.begin(9600);
+
+  pinMode(SIGNAL_PIN, OUTPUT);
+  digitalWrite(SIGNAL_PIN, LOW); 
+
+  UltrasonicInterrupt::setup(pingPulseComplete, INTERRUPT_PIN);
+}
+
+
+void loop() {
+  
+  unsigned long time = millis();
+  unsigned long dt   = time - lastTime;
+  lastTime 	     = time;
+  
+  pingTimer += dt;
+  if(pingTimer > pingDelay){
+	pingTimer = 0;
+	ping();
+  }
+  
+  // do stuff...  
+}
+
+
+/**
+* Trigger the outward ping pulse(s)
+*/
+void ping(){
+
+ // Serial.println("ping out");
+  
+  digitalWrite(SIGNAL_PIN, HIGH);
+  delayMicroseconds(10); // I think I can cope with blocking for a whole 10us here...
+  digitalWrite(SIGNAL_PIN, LOW);
+  
+  // start listening out for the echo pulse on interrupt 0
+  UltrasonicInterrupt::begin();
+}
+
+
+/**
+* Pulse complete callback hanlder for PulseInZero 
+* @param duration - pulse length in microseconds
+*/
+void pingPulseComplete(unsigned long duration) {
+
+  millimetres = MicrosecondsToMillimetres2 * duration;
+  
+  if(millimetres > 4000){
+       Serial.println("out of range");
+       // out of range (http://users.ece.utexas.edu/~valvano/Datasheets/HCSR04b.pdf)
+       millimetres = 4000;
+  } else {
+      Serial.print("duration: ");
+      Serial.print(duration);
+      Serial.print(" us, distance: ");
+      Serial.print(millimetres);
+      Serial.println(" mm");
+  }
+}

+

--- /dev/null
+++ b/UltrasonicSensor/libraries/UltrasonicInterrupt/README.md
@@ -1,1 +1,3 @@
+Use a hardware interrupt to emulate the Arduino::pulseIn functionality without pausing code execution while waiting for the pulse
+See http://arduino.cc/en/Reference/Interrupts
 

--- /dev/null
+++ b/UltrasonicSensor/libraries/UltrasonicInterrupt/UltrasonicInterrupt.cpp
@@ -1,1 +1,72 @@
+#include "Arduino.h"
+#include "UltrasonicInterrupt.h"
 
+// initialise static vars
+bool UltrasonicInterrupt::state = false;
+bool UltrasonicInterrupt::active = false;
+int UltrasonicInterrupt::interrupt = 0;
+
+void (*UltrasonicInterrupt::onComplete)(unsigned long) = NULL;
+
+
+/**
+*
+*
+**/
+void UltrasonicInterrupt::setup(void (*pulseComplete)(unsigned long), int customInterrupt ){
+	onComplete 	= pulseComplete;
+	active 		= false;
+	interrupt   = customInterrupt;
+}
+
+
+/**
+* @public
+* Start listening on the desired interrupt for a pulse
+*/
+void UltrasonicInterrupt::begin(){
+	state		= false;
+	active 		= true;
+	attachInterrupt(interrupt, pinChange, RISING);
+}
+
+
+/**
+* @public
+* There's no timeout with this class: it will listen indefinitely for a change on the interrupt pin.
+* Use abandon to stop waiting for a pulse.
+*/
+void UltrasonicInterrupt::abandon(){
+	if(active){
+		state =  active = false;
+		detachInterrupt(interrupt);
+	}
+}
+
+
+/**
+* @static
+* interrupt handler - called whenever the interrupt pin state changes
+*/
+void UltrasonicInterrupt::pinChange(){
+
+	static unsigned long pulseStart = 0;
+
+	state = !state;
+
+	if(state){
+		// interrupt pin has changed, a pulse has started
+		pulseStart = micros(); // store the current microseconds
+		attachInterrupt(interrupt, pinChange, FALLING); // now wait for the falling edge
+	} else {
+
+		// pulse complete, detach the interrupt...
+		detachInterrupt(interrupt);
+
+		// pin state changed again - pulse ended
+		unsigned long duration = micros() - pulseStart; // get the pulse length
+
+		active = false;
+		onComplete(duration);
+	}
+}

--- /dev/null
+++ b/UltrasonicSensor/libraries/UltrasonicInterrupt/UltrasonicInterrupt.h
@@ -1,1 +1,26 @@
+#ifndef UltrasonicInterrupt_h
+#define UltrasonicInterrupt_h
 
+#include "Arduino.h"
+
+class UltrasonicInterrupt {
+
+	public:
+
+		static void setup(void (*callback)(unsigned long), int customInterrupt);
+
+		static void begin();
+		static void abandon();
+
+		static bool active;
+		static bool state;
+		static int interrupt;
+
+		static void (*onComplete)(unsigned long);
+
+	    // interrupt handler
+		static void pinChange();
+
+};
+
+#endif

comments