-
-
Save harrisonhjones/dd448010b905f60d3129 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// -------------------------------------------- // | |
// Documentation | |
// ------------------ | |
// -------------------------------------------- // | |
// Compiler Defines | |
// ------------------ | |
#define APP_VERSION 1.2 // Keep track of what version this code is | |
#define NUM_MEASUREMENTS 20 // The number of measurements we want to take befoe averaging and publishing | |
// -------------------------------------------- // | |
// Includes (Libraries & Other Files) | |
// ------------------ | |
#include "elapsedMillis/elapsedMillis.h" // ElapsedMillis Library for keeping track of timers/time | |
// -------------------------------------------- // | |
// Variables | |
// ------------------ | |
const int trigPin = D0; // Define which pin we are using for the sensor trigger | |
const int echoPin = D1; | |
const int led = D7; | |
bool active = FALSE; // Define a boolean to keep track of our state (on or off) | |
bool prevActive = active; | |
int readingIndex = 0; // Define a variable to keep track of what reading we are on | |
double distances[NUM_MEASUREMENTS]; // Define an array of doubles to keep track of our measurements | |
double avgDistance = 0.0; // Define a variable to keep track of the average distance | |
unsigned long publishInterval = 4000; // Define a variable to pace how often we publishEvery 4000 ms (4 seconds) | |
unsigned long refractoryPeriod = 10000; // Define a variable to pace how often we refactor | |
elapsedMillis pTimeElapsed; // Define a timer to keep track of how often we publish | |
elapsedMillis rTimeElapsed; // Define a timer to keep track of how often we refactor | |
elapsedMillis tmrUpdate; // Define a timer to keep track of how often we take new measurements | |
unsigned long measurementInterval = 100; // Define a variable to pace how often we take new measurements every 100 miliseconds | |
// -------------------------------------------- // | |
// Function - setup - Runs once at boot | |
// ------------------ | |
void setup() { | |
// Define a Spark Variable for grabbing the measured distance | |
Spark.variable("distance", &avgDistance, DOUBLE); | |
// Define a Spark function for ativating something | |
Spark.function("activation", activation); | |
// Define our pin mode so our pins in the correct state (input or output) | |
// Set the pin for the sensor trigger as an output | |
pinMode(trigPin, OUTPUT); | |
// pinMode(echoPin, INPUT); | |
// Set the pin for the status led (onboard) as an output | |
pinMode(led, OUTPUT); | |
// Let the world know we have started up and what version of the code we are running | |
Spark.publish("status", "{ status: \"started up! "+String(APP_VERSION)+"\"}", 60, PRIVATE ); | |
// Reset the two timers | |
rTimeElapsed = 0; | |
pTimeElapsed = 0; | |
} | |
// -------------------------------------------- // | |
l// Funtion - Loop - Runs indefintely | |
// ------------------ | |
void loop() { | |
if (active) { | |
// Externally indicate that we are in an active measurement mode | |
digitalWrite(led, HIGH); | |
// Only take new measurements every 100 ms | |
if(tmrUpdate > measurementInterval) | |
{ | |
tmrUpdate = 0; | |
updateDistance(); | |
} | |
} else { | |
digitalWrite(led, LOW); | |
} | |
} | |
// -------------------------------------------- // | |
// Function - activation - Runs when called by the Spark Function. Activates/deactivates measurement | |
// ------------------ | |
// Turn on/off sensor measurement. | |
int activation(String state) { | |
// Let the world know the sensor is on/off | |
Spark.publish("status", "{ Sensor Activation: " + state +"}"); | |
// Reset our variables to their default state | |
pTimeElapsed = 0; | |
rTimeElapsed = 0; | |
readingIndex = 0; | |
if (state == "on") { | |
active = TRUE; | |
} else { | |
active = FALSE; | |
} | |
return 1; | |
} | |
// -------------------------------------------- // | |
// Function - updateDistance - Takes distance measurements and sends them to be published when enough have been collected | |
// ------------------ | |
void updateDistance() { | |
// If we are still taking new measurements then take a new measurement | |
if (readingIndex < NUM_MEASUREMENTS) { | |
// Define a local varible to keep track of the incoming reading | |
long echo = 0; | |
// Activate the sensor with a short series of pulses | |
pinMode(trigPin, OUTPUT); | |
digitalWrite(trigPin, LOW); // Send low pulse | |
delayMicroseconds(2); // Wait for 2 microseconds | |
digitalWrite(trigPin, HIGH); // Send high pulse | |
delayMicroseconds(5); // Wait for 5 microseconds | |
digitalWrite(trigPin, LOW); // Holdoff | |
// Switch our trigger pin to be a input so we can read the incoming data | |
// please note that pulseIn has a 1sec timeout, which may | |
// not be desirable. Depending on your sensor specs, you | |
// can likely bound the time like this -- marcmerlin | |
// echo = pulseIn(ultraSoundSignal, HIGH, 38000) | |
pinMode(trigPin, INPUT); | |
// Take a reading, convert it into centimeters, and save it to our data array | |
echo = pulseIn(trigPin, HIGH); //Listen for echo | |
distances[readingIndex++] = microsecondsToCentimeters(echo); | |
// If we have taken NUM_MEASUREMENTS measurements then publish the data and clear the index | |
} else { | |
publishDistance(); | |
readingIndex = 0; | |
} | |
} | |
// -------------------------------------------- // | |
// Function - publishDistance - Publish the data to the world! The Particle cloud currently limits the publish rate to 1 Hz or 4 Hz in burst. | |
// ------------------ | |
void publishDistance() { | |
// Calculate the average distance (use the global avgDistance) | |
for (int i=0; i<NUM_MEASUREMENTS; i++) | |
{ | |
avgDistance += distances[i]; | |
} | |
avgDistance = avgDistance / NUM_MEASUREMENTS; | |
if (pTimeElapsed > publishInterval) { | |
char publishBuffer[63]; | |
// Publish the average distance (as "{avgDistance:#}") | |
sprintf(publishBuffer,"{avgDistance:%.1f}"); | |
Spark.publish("status", publishBuffer); | |
// Publish the first 10 distances (as "{distances:#,#,#,#,#,#,#,#,#,#}") | |
sprintf(publishBuffer,"{distances:%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f}",distances[0],distances[1],distances[2],distances[3],distances[4],distances[5],distances[6],distances[7],distances[8],distances[9]); | |
Spark.publish("status", publishBuffer); | |
// Publish the next 10 distances (as "{distances:#,#,#,#,#,#,#,#,#,#}") | |
sprintf(publishBuffer,"{distances:%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f}",distances[10],distances[11],distances[12],distances[13],distances[14],distances[15],distances[16],distances[17],distances[18],distances[19]); | |
Spark.publish("status", publishBuffer); | |
// Publish the current distance state (far or near) | |
if (avgDistance < 100) { | |
Spark.publish("distance", "near"); | |
} else { | |
Spark.publish("distance", "far"); | |
} | |
// Reset out timer(s) | |
rTimeElapsed = 0; | |
pTimeElapsed = 0; | |
} | |
} | |
// -------------------------------------------- // | |
// Function - microsecondsToCentimeters - Convert our raw reading into a distance measurement | |
// ------------------ | |
double microsecondsToCentimeters(long microseconds) { | |
// The speed of sound is 340 m/s or 29 microseconds per centimeter. | |
// The ping travels out and back, so to find the distance of the | |
// object we take half of the distance travelled. | |
return (double) microseconds / 29.0 / 2.0; | |
} | |
// -------------------------------------------- // | |
// Function - pulseIn - PulseIn function for the Spark Core | |
// ------------------ | |
unsigned long pulseIn(uint16_t pin, uint8_t state) { | |
GPIO_TypeDef* portMask = (PIN_MAP[pin].gpio_peripheral); // Cache the target's peripheral mask to speed up the loops. | |
uint16_t pinMask = (PIN_MAP[pin].gpio_pin); // Cache the target's GPIO pin mask to speed up the loops. | |
unsigned long pulseCount = 0; // Initialize the pulseCount variable now to save time. | |
unsigned long loopCount = 0; // Initialize the loopCount variable now to save time. | |
unsigned long loopMax = 20000000; // Roughly just under 10 seconds timeout to maintain the Spark Cloud connection. | |
// Wait for the pin to enter target state while keeping track of the timeout. | |
while (GPIO_ReadInputDataBit(portMask, pinMask) != state) { | |
if (loopCount++ == loopMax) { | |
return 0; | |
} | |
} | |
// Iterate the pulseCount variable each time through the loop to measure the pulse length; we also still keep track of the timeout. | |
while (GPIO_ReadInputDataBit(portMask, pinMask) == state) { | |
if (loopCount++ == loopMax) { | |
return 0; | |
} | |
pulseCount++; | |
} | |
// Return the pulse time in microseconds by multiplying the pulseCount variable with the time it takes to run once through the loop. | |
return pulseCount * 0.405; // Calculated the pulseCount++ loop to be about 0.405uS in length. | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment