Hi Guys,
Thought Id share with you my first project with Electric IMP. The inspiration and credit for this goes to:
http://alexba.in/blog/2014/01/06/receiving-sms-notifications-from-your-washer/
I was able to order all the parts from adafruit.com (shipped to Australia in only 5 days great service).
I have made some modifications to the code as some tweaking to settings and sms function was not working.
I have left the code for logging to Firebase (as i didn’t test it).
I’m thinking next embed on the agent a webpage for the current status of the washing. There are still a couple of pins spare so i can attach more, any thoughts suggestions welcome.
Code here:
`
// Run on Agent
// Thresholds to adjust for better accuracy
dataThreshold <- 270; // Minimum accelerometer value to count as ON
onThreshold <- 30; // Number of ON samples before machine enters RUNNING state
offThreshold <- 30; // Number of OFF samples before machine enters OFF state
// State variable
running <- false;
// Keep track of counts
onCount <- 0;
offCount <- 0;
// Twilo code for sending SMS
TWILIO_ACCOUNT_SID <- “xxxxxxxxxxxxxxxxxxxxxxxxxx” // your twilio account SID goes here
TWILIO_AUTH_TOKEN <- “xxxxxxxxxxxxxxxxxxxxxxxxxx” // your twilio passkey goes here
TWILIO_FROM_NUMBER <- “+16xxxxxxxx” // your twilio phone number goes here
// Function for sending SMS via Twilio
function send_sms (number, message) {
local twilio_url = format(“https://api.twilio.com/2010-04-01/Accounts/%s/SMS/Messages.json"”, TWILIO_ACCOUNT_SID);
local auth = “Basic " + http.base64encode(TWILIO_ACCOUNT_SID+”:"+TWILIO_AUTH_TOKEN);
local body = http.urlencode({From=TWILIO_FROM_NUMBER, To=number, Body=message});
local req = http.post(twilio_url, {Authorization=auth}, body);
local res = req.sendsync();
//server.log(auth);
if(res.statuscode != 201) {
server.log("error sending message: "+res.body);
}
}
// Array of phone numbers to be contacted with the laundry is done
phoneNumbers <- ["+61xxxxxxxxx", “+61xxxxxxxxx”];
// Firebase
logToFirebase <- false;
firebaseURL <- “https://FIREBASE_URL.firebaseIO.com/data.json”;
firebaseHeaders <- { “Content-Type”: “application/json” };
// Called every time the imp emits data
device.on(“data”, function(data) {
// Is there enough accelerometer activity for the device to be considered ON?
if (data >= dataThreshold) {
onCount = onCount + 1;
// Prevent overflow errors by resetting onCount when it gets close to limit
if (onCount >= 65500) {
onCount = onThreshold;
}
// If the device has been ON for long enough, set running state to be true
if (onCount >= onThreshold) {
running = true;
// Running, so reset offCount
offCount = 0;
}
// debug / logs
if (running == true) {
server.log(format("ON - RUNNING (%f), onCount (%d), offCount (%d)", data, onCount, offCount));
} else {
server.log(format("ON (%f), onCount (%d), offCount (%d)", data, onCount, offCount));
}
// Imp is not recording much accelerometer movement, so device seems to be OFF
} else {
offCount = offCount + 1;
// Prevent overflow errors by resetting offCount when it gets close to limit
if (offCount >= 65500) {
offCount = offThreshold;
}
// Has the device been off for long enough to be "done"?
if (offCount >= offThreshold) {
// Was the device previously running?
if (running == true) {
// This means that the laundry had been running, and is now done.
// Send an SMS to each phone number in the phoneNumbers array.
foreach (number in phoneNumbers) {
send_sms(number, "Candice your washing has finished!")
}
// debug / logs
server.log("!!!! Emitting OFF event !!!!");
}
// Reset on count
onCount = 0;
// Machine is no longer running
running = false;
}
// debug / logs
if (running == true) {
server.log(format("OFF - WAS RUNNING (%f), onCount (%d), offCount (%d)", data, onCount, offCount));
} else {
server.log(format("OFF (%f), onCount (%d), offCount (%d)", data, onCount, offCount));
}
}
if (logToFirebase == true) {
// Build a post request to Firebase to log the data
local body = format("{\"amount\": %f, \"running\": %s, \".priority\": %d}", data, running ? "true" : "false", time());
local request = http.post(firebaseURL, firebaseHeaders, body);
// Send the data to Firebase async
local response = request.sendasync(function(done) {});
}
});
`
`
// Run on Device
total <- 0; // Sum of % change from all samples
n <- 0; // Counter for number of samples read
last <- 1; // Previous reading of magnitude
function readSensor() {
// Time interval
local interval = 0.02;
// Get source voltage, should be 3.3V
local vRef = hardware.voltage();
// Read in ADC values from accelerometer
local adcRx = hardware.pin1.read();
local adcRy = hardware.pin2.read();
local adcRz = hardware.pin5.read();
// server.log(format("Raw ADC values: %f, %f, %f", adcRx, adcRy, adcRz));
// Convert 16bit ADC accelerometer values (0-65535) into voltage
local voltsRx = (adcRx * vRef) / 65535.0;
local voltsRy = (adcRy * vRef) / 65535.0;
local voltsRz = (adcRz * vRef) / 65535.0;
// server.log(format("Voltages: %f, %f %f", voltsRx, voltsRy, voltsRz));
// Subtract 0g (1.5V at 3V, 1.65V at 3.3V)
local deltaVoltsRx = voltsRx - (vRef / 2);
local deltaVoltsRy = voltsRy - (vRef / 2);
local deltaVoltsRz = voltsRz - (vRef / 2);
// server.log(format("Adjusted voltages %f, %f, %f", deltaVoltsRx, deltaVoltsRy, deltaVoltsRz));
// Convert from voltage to g, using sensitivity of 300mV
local rX = deltaVoltsRx / 0.3;
local rY = deltaVoltsRy / 0.3;
local rZ = deltaVoltsRz / 0.3;
//server.log(format("Gs: %f, %f, %f", rX, rY, rZ));
// Compute magnitude of force
local magnitude = math.sqrt(math.pow(rX,2) + math.pow(rY, 2) + math.pow(rZ, 2));
// Compute % change since last reading
local change = math.fabs((magnitude - last)/last) * 100.0;
// Store magnitude in last for next time
last = magnitude;
// Log magnitude and percent change
// server.log(format("magnitude: %f, change amount: %f", magnitude, change));
// Increment total with % change, increment N
total = total + change;
n = n + 1;
// Log data to server once ever 250 samples (8 seconds)
// Log data to server once ever 170 samples (5 seconds) new threshold
if (n >= 170) {
agent.send("data", total);
n = 0;
total = 0;
}
// Sleep until time to read sensor again
imp.wakeup(interval, readSensor);
}
// X input
hardware.pin1.configure(ANALOG_IN);
// Y input
hardware.pin2.configure(ANALOG_IN);
// Z input
hardware.pin5.configure(ANALOG_IN);
// Start reading the sensor
readSensor();
`