Pics
Indicator light
Little video showing the Blue breathing light inside turning green for a couple of seconds when pressed
Instructions
Start by printing the plastic parts.. the cover and base are easy prints. I printed face down to get a smooth finish, cleaned up with a razor blade and then smoothed them off in an Acetone vapor bath. the button is a dual color print and there is a ring around the outside you will need to cut off, I added it in to make a bridge. All up it took about 2.5 hours to print. The face of the button is all white, but only 0.2mm thick in places with clear behind so the light shows through and shows the Spark logo
With the Spark core, I started by removing the header pins from the spark to make it thinner. Its easy to remove the black plastic with a jewelers screwdriver then desolder each pin. Copy the code to the Web IDE and change the info to suit.. its all at the top and should be self explanitory. Flash the code and test by connecting a piezo speaker from D6 to GND and touch D0 to Gnd to trigger the code. If its not working try changing the 'boolean DEBUG = false;' to true. You will need to open up a terminal (9600 baud) when the blue led comes on and press enter to start the code running. It will give you the Wifi info first, then when you connect D0 to Gnd, it will show connecting and then if it connects, the Get request and headers. After a second or three you should see the response, and then it will go onto the next section and do the same again.
For the main part of the build, I made 2 strips of Vero board, 3 lines wide, with 2 surface mount tactile switches on each. the switches are 6mm square and about 4.5mm high. I drilled out holes to mount these inside the cover and screwed them in using #4 x 6mm screws. the spark core should fit between the 2 strips nicely. i then soldered links from D0 to the nearest hole in the vero board. and A0 to its nearest hole too (only needed for support). I soldered the Gnd to the outside stipe of the vero board on each side. I also made a link from D0 to A0 (well where they connect on the Vero board anyway)
It now has a RTTTL (polyphonic ringtone) output on D6. You can hook up a piezo speaker directly if you dont need it too loud, or hook up a set of amplified computer speakers. I used a set (TDK XA-10) with a very small amplifier in the USB connection, I stripped it down and put it inside the doorbell. I took the usb connector off and took power from the same supply i use for the Spark. Then hook up D6 to both left and right inputs, and connect 2 wires to each of the outputs, left and right. One output is near the front of the house and the other out the back.. at each speaker i have put a 100k pot with outside terminals connected to the output from the amp and the center tap to the speaker, and the other side of the speaker to one of the wires (whichever one makes it work the right way, clockwise for volume up)
Thats pretty much the doorbell complete, just needs power to Vin and Gnd.
To setup the XBMC side of things you will need this plugin: http://forum.xbmc.org/showthread.php?tid=182540 and a compatible camera
Pushingbox is the main part of the doorbell so you will need to set up an account with at least 1 scenario to make it work http://www.pushingbox.com/
Future developments
I plan on adding a little piezo buzzer in the button to give some feedback - Done, Actually i added RTTTL ringtones to it. and run a amplified PC speaker off D6. It now plays the ringtone before connecting to Pushingbox and XBMC. Its super loud and there are heaps of tunes to choose from, just un-comment the line you want to play
I also need to update the code to retry connections a couple of times if it fails to connect. - Done, if it fails to connect it will retry each connection 5 times with a second of delay between each attempt
I will eventually add a fingerprint reader and a RFID reader to the Spark too for key-less entry.. - Progressing nicely, Library for fingerprint reader is ported to work with the Spark core, tested and working. Still waiting for the RFID reader to be able to test it, library is also ported and ready. Currently working on a database for users names and welcome messages and to keep a log of entry's, these will be stored on a SD card.
Code
Code
Warning: Embedding code files within the project story has been deprecated. To edit this file or add more files, go to the "Software" tab. To remove this file from the story, click on it to trigger the context menu, then click the trash can button (this won't delete it from the "Software" tab).
#include "application.h"
// XBMC Setup
char xbmcServer[] = "your server"; // XBMC Server
int xbmcPort = 80; // XBMC Port
char xbmcScript[] = "/jsonrpc?request={%22jsonrpc%22:%222.0%22,%22method%22:%22Addons.ExecuteAddon%22,%22params%22:{%22addonid%22:%22script.securitycam%22},%22id%22:%221%22}}"; // Script to run
char xbmcLogon[] = "Base64encoded"; // Username:Password base64 encoded
// Pushing Box Setup
char serverName[] = "api.pushingbox.com"; // Pushingbox Server
char deviceID[] = "/pushingbox?devid=YOURDEVIDHERE"; // Get request
// Select a Tune from below
//char *song = (char *)"The Simpsons:d=4,o=5,b=168:c.6,e6,f#6,8a6,g.6,e6,c6,8a,8f#,8f#,8f#,2g,8p,8p,8f#,8f#,8f#,8g,a#.,8c6,8c6,8c6,c6";
//char *song = (char *)"Indiana:d=4,o=5,b=250:e,8p,8f,8g,8p,1c6,8p.,d,8p,8e,1f,p.,g,8p,8a,8b,8p,1f6,p,a,8p,8b,2c6,2d6,2e6,e,8p,8f,8g,8p,1c6,p,d6,8p,8e6,1f.6,g,8p,8g,e.6,8p,d6,8p,8g,e.6,8p,d6,8p,8g,f.6,8p,e6,8p,8d6,2c6";
//char *song = (char *)"TakeOnMe:d=4,o=4,b=160:8f#5,8f#5,8f#5,8d5,8p,8b,8p,8e5,8p,8e5,8p,8e5,8g#5,8g#5,8a5,8b5,8a5,8a5,8a5,8e5,8p,8d5,8p,8f#5,8p,8f#5,8p,8f#5,8e5,8e5,8f#5,8e5,8f#5,8f#5,8f#5,8d5,8p,8b,8p,8e5,8p,8e5,8p,8e5,8g#5,8g#5,8a5,8b5,8a5,8a5,8a5,8e5,8p,8d5,8p,8f#5,8p,8f#5,8p,8f#5,8e5,8e5";
//char *song = (char *)"Entertainer:d=4,o=5,b=140:8d,8d#,8e,c6,8e,c6,8e,2c.6,8c6,8d6,8d#6,8e6,8c6,8d6,e6,8b,d6,2c6,p,8d,8d#,8e,c6,8e,c6,8e,2c.6,8p,8a,8g,8f#,8a,8c6,e6,8d6,8c6,8a,2d6";
//char *song = (char *)"Muppets:d=4,o=5,b=250:c6,c6,a,b,8a,b,g,p,c6,c6,a,8b,8a,8p,g.,p,e,e,g,f,8e,f,8c6,8c,8d,e,8e,8e,8p,8e,g,2p,c6,c6,a,b,8a,b,g,p,c6,c6,a,8b,a,g.,p,e,e,g,f,8e,f,8c6,8c,8d,e,8e,d,8d,c";
//char *song = (char *)"Xfiles:d=4,o=5,b=125:e,b,a,b,d6,2b.,1p,e,b,a,b,e6,2b.,1p,g6,f#6,e6,d6,e6,2b.,1p,g6,f#6,e6,d6,f#6,2b.,1p,e,b,a,b,d6,2b.,1p,e,b,a,b,e6,2b.,1p,e6,2b.";
//char *song = (char *)"Looney:d=4,o=5,b=140:32p,c6,8f6,8e6,8d6,8c6,a.,8c6,8f6,8e6,8d6,8d#6,e.6,8e6,8e6,8c6,8d6,8c6,8e6,8c6,8d6,8a,8c6,8g,8a#,8a,8f";
//char *song = (char *)"20thCenFox:d=16,o=5,b=140:b,8p,b,b,2b,p,c6,32p,b,32p,c6,32p,b,32p,c6,32p,b,8p,b,b,b,32p,b,32p,b,32p,b,32p,b,32p,b,32p,b,32p,g#,32p,a,32p,b,8p,b,b,2b,4p,8e,8g#,8b,1c#6,8f#,8a,8c#6,1e6,8a,8c#6,8e6,1e6,8b,8g#,8a,2b";
//char *song = (char *)"Bond:d=4,o=5,b=80:32p,16c#6,32d#6,32d#6,16d#6,8d#6,16c#6,16c#6,16c#6,16c#6,32e6,32e6,16e6,8e6,16d#6,16d#6,16d#6,16c#6,32d#6,32d#6,16d#6,8d#6,16c#6,16c#6,16c#6,16c#6,32e6,32e6,16e6,8e6,16d#6,16d6,16c#6,16c#7,c.7,16g#6,16f#6,g#.6";
//char *song = (char *)"MASH:d=8,o=5,b=140:4a,4g,f#,g,p,f#,p,g,p,f#,p,2e.,p,f#,e,4f#,e,f#,p,e,p,4d.,p,f#,4e,d,e,p,d,p,e,p,d,p,2c#.,p,d,c#,4d,c#,d,p,e,p,4f#,p,a,p,4b,a,b,p,a,p,b,p,2a.,4p,a,b,a,4b,a,b,p,2a.,a,4f#,a,b,p,d6,p,4e.6,d6,b,p,a,p,2b";
//char *song = (char *)"StarWars:d=4,o=5,b=45:32p,32f#,32f#,32f#,8b.,8f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32e6,8c#.6,32f#,32f#,32f#,8b.,8f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32e6,8c#6";
//char *song = (char *)"GoodBad:d=4,o=5,b=56:32p,32a#,32d#6,32a#,32d#6,8a#.,16f#.,16g#.,d#,32a#,32d#6,32a#,32d#6,8a#.,16f#.,16g#.,c#6,32a#,32d#6,32a#,32d#6,8a#.,16f#.,32f.,32d#.,c#,32a#,32d#6,32a#,32d#6,8a#.,16g#.,d#";
//char *song = (char *)"TopGun:d=4,o=4,b=31:32p,16c#,16g#,16g#,32f#,32f,32f#,32f,16d#,16d#,32c#,32d#,16f,32d#,32f,16f#,32f,32c#,16f,d#,16c#,16g#,16g#,32f#,32f,32f#,32f,16d#,16d#,32c#,32d#,16f,32d#,32f,16f#,32f,32c#,g#";
//char *song = (char *)"A-Team:d=8,o=5,b=125:4d#6,a#,2d#6,16p,g#,4a#,4d#.,p,16g,16a#,d#6,a#,f6,2d#6,16p,c#.6,16c6,16a#,g#.,2a#";
//char *song = (char *)"Flinstones:d=4,o=5,b=40:32p,16f6,16a#,16a#6,32g6,16f6,16a#.,16f6,32d#6,32d6,32d6,32d#6,32f6,16a#,16c6,d6,16f6,16a#.,16a#6,32g6,16f6,16a#.,32f6,32f6,32d#6,32d6,32d6,32d#6,32f6,16a#,16c6,a#,16a6,16d.6,16a#6,32a6,32a6,32g6,32f#6,32a6,8g6,16g6,16c.6,32a6,32a6,32g6,32g6,32f6,32e6,32g6,8f6,16f6,16a#.,16a#6,32g6,16f6,16a#.,16f6,32d#6,32d6,32d6,32d#6,32f6,16a#,16c.6,32d6,32d#6,32f6,16a#,16c.6,32d6,32d#6,32f6,16a#6,16c7,8a#.6";
//char *song = (char *)"Jeopardy:d=4,o=6,b=125:c,f,c,f5,c,f,2c,c,f,c,f,a.,8g,8f,8e,8d,8c#,c,f,c,f5,c,f,2c,f.,8d,c,a#5,a5,g5,f5,p,d#,g#,d#,g#5,d#,g#,2d#,d#,g#,d#,g#,c.7,8a#,8g#,8g,8f,8e,d#,g#,d#,g#5,d#,g#,2d#,g#.,8f,d#,c#,c,p,a#5,p,g#.5,d#,g#";
char *song = (char *)"Gadget:d=16,o=5,b=50:32d#,32f,32f#,32g#,a#,f#,a,f,g#,f#,32d#,32f,32f#,32g#,a#,d#6,4d6,32d#,32f,32f#,32g#,a#,f#,a,f,g#,f#,8d#";
//char *song = (char *)"Smurfs:d=32,o=5,b=200:4c#6,16p,4f#6,p,16c#6,p,8d#6,p,8b,p,4g#,16p,4c#6,p,16a#,p,8f#,p,8a#,p,4g#,4p,g#,p,a#,p,b,p,c6,p,4c#6,16p,4f#6,p,16c#6,p,8d#6,p,8b,p,4g#,16p,4c#6,p,16a#,p,8b,p,8f,p,4f#";
//char *song = (char *)"MahnaMahna:d=16,o=6,b=125:c#,c.,b5,8a#.5,8f.,4g#,a#,g.,4d#,8p,c#,c.,b5,8a#.5,8f.,g#.,8a#.,4g,8p,c#,c.,b5,8a#.5,8f.,4g#,f,g.,8d#.,f,g.,8d#.,f,8g,8d#.,f,8g,d#,8c,a#5,8d#.,8d#.,4d#,8d#.";
//char *song = (char *)"LeisureSuit:d=16,o=6,b=56:f.5,f#.5,g.5,g#5,32a#5,f5,g#.5,a#.5,32f5,g#5,32a#5,g#5,8c#.,a#5,32c#,a5,a#.5,c#.,32a5,a#5,32c#,d#,8e,c#.,f.,f.,f.,f.,f,32e,d#,8d,a#.5,e,32f,e,32f,c#,d#.,c#";
//char *song = (char *)"MissionImp:d=16,o=6,b=95:32d,32d#,32d,32d#,32d,32d#,32d,32d#,32d,32d,32d#,32e,32f,32f#,32g,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,a#,g,2d,32p,a#,g,2c#,32p,a#,g,2c,a#5,8c,2p,32p,a#5,g5,2f#,32p,a#5,g5,2f,32p,a#5,g5,2e,d#,8d";
//char *song = (char *)"SMBtheme:d=4,o=5,b=100:16e6,16e6,32p,8e6,16c6,8e6,8g6,8p,8g,8p,8c6,16p,8g,16p,8e,16p,8a,8b,16a#,8a,16g.,16e6,16g6,8a6,16f6,8g6,8e6,16c6,16d6,8b,16p,8c6,16p,8g,16p,8e,16p,8a,8b,16a#,8a,16g.,16e6,16g6,8a6,16f6,8g6,8e6,16c6,16d6,8b,8p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16g#,16a,16c6,16p,16a,16c6,16d6,8p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16c7,16p,16c7,16c7,p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16g#,16a,16c6,16p,16a,16c6,16d6,8p,16d#6,8p,16d6,8p,16c6";
//char *song = (char *)"SMBunderground:d=16,o=6,b=100:c,c5,a5,a,a#5,a#,2p,8p,c,c5,a5,a,a#5,a#,2p,8p,f5,f,d5,d,d#5,d#,2p,8p,f5,f,d5,d,d#5,d#,2p,32d#,d,32c#,c,p,d#,p,d,p,g#5,p,g5,p,c#,p,32c,f#,32f,32e,a#,32a,g#,32p,d#,b5,32p,a#5,32p,a5,g#5";
//char *song = (char *)"SMBwater:d=8,o=6,b=225:4d5,4e5,4f#5,4g5,4a5,4a#5,b5,b5,b5,p,b5,p,2b5,p,g5,2e.,2d#.,2e.,p,g5,a5,b5,c,d,2e.,2d#,4f,2e.,2p,p,g5,2d.,2c#.,2d.,p,g5,a5,b5,c,c#,2d.,2g5,4f,2e.,2p,p,g5,2g.,2g.,2g.,4g,4a,p,g,2f.,2f.,2f.,4f,4g,p,f,2e.,4a5,4b5,4f,e,e,4e.,b5,2c.";
//char *song = (char *)"SMBdeath:d=4,o=5,b=90:32c6,32c6,32c6,8p,16b,16f6,16p,16f6,16f.6,16e.6,16d6,16c6,16p,16e,16p,16c";
//char *song = (char *)"RickRoll:d=4,o=5,b=200:8g,8a,8c6,8a,e6,8p,e6,8p,d6.,p,8p,8g,8a,8c6,8a,d6,8p,d6,8p,c6,8b,a.,8g,8a,8c6,8a,2c6,d6,b,a,g.,8p,g,2d6,2c6.,p,8g,8a,8c6,8a,e6,8p,e6,8p,d6.,p,8p,8g,8a,8c6,8a,2g6,b,c6.,8b,a,8g,8a,8c6,8a,2c6,d6,b,a,g.,8p,g,2d6,2c6.";
//char *song = (char *)"2.34kHzBeeps:d=4,o=7,b=240:d,p,d,p,d,p,d,p";
//char *song = (char *)"Satellit:d=8,o=6,b=112:g,e,16f,16e,d,c,g,c7,c";
// Input and Output Pins
int16_t tonePin = D6; //Dorrbell Sound Output
int doorbell = D0; // Doorbell button connects to D0 on the core
int LED = D7; // Built in LED
boolean DEBUG = false; // enable or disable Debug
int Retrys = 5; // Number of times to retry connecting
// RTTTL setup
int notes[] =
{0,
3817,3597,3401,3205,3030,2857,2703,2551,2404,2273,2146,2024,
1908,1805,1701,1608,1515,1433,1351,1276,1205,1136,1073,1012,
956,903,852,804,759,716,676,638,602,568,536,506,
478,451,426,402,379,358,338,319,301,284,268,253,
239,226,213,201,190,179,169,159,151,142,134,127};
#define OCTAVE_OFFSET 0
boolean playing = false;
byte default_dur = 4;
byte default_oct = 6;
byte lowest_oct = 3;
int bpm = 63;
int num;
long wholenote;
long duration;
byte note;
byte scale;
bool songDone = false;
char *songPtr;
unsigned long Lockout; // used to stop flooding servers
void setup() {
pinMode(tonePin,OUTPUT);
pinMode(doorbell, INPUT_PULLUP); // other side of doorbell will connect to ground to pull low
Lockout = millis();
pinMode(LED, OUTPUT); // sets LED as output
if(DEBUG){
digitalWrite(LED,HIGH); // Light the onboard LED so you know it's time to open your Serial Terminal
Serial.begin(9600);
while(!Serial.available()); // wait here for user to press ENTER in Serial Terminal
digitalWrite(LED,LOW);
Serial.print("SSID: ");
Serial.println(Network.SSID());
Serial.print("Core IP: ");
Serial.println(Network.localIP());
Serial.print("Gateway: ");
Serial.println(Network.gatewayIP());
Serial.print("Mask: ");
Serial.println(Network.subnetMask());
Serial.print("WiFi RSSI: ");
Serial.println(Network.RSSI());
}
}
void loop() {
if (millis() >= Lockout){ // check how long its been since last pushed
if(digitalRead(doorbell) == LOW) { //read the doorbell button
delay(50);
if(digitalRead(doorbell) == LOW) { // debounce check again to make sure
Lockout = millis() + 15000; // set up the lockout period 15 seconds before it will run again
RGB.control(true);
RGB.color(0,255,0);
playing = true;
while(playing) {
if(!songDone) { // Start song
songDone = true;
begin_rtttl(song);
}
if(!next_rtttl()) { // Play next note
songDone = false;
playing = false;
delay(2000);
}
}
runXbmcScript(xbmcServer, xbmcPort, xbmcScript, xbmcLogon, Retrys); // opens up a script in xbmc that displays an ip camera
sendToPushingBox(serverName, deviceID, Retrys); // sends push notification to mobile phone or sends email using pushingbox
RGB.control(false);
}
}
}
}
void runXbmcScript(char *hostname, int port, char *url, char *xbmclogon, int retry) {
TCPClient client;
char line[255];
client.stop();
//digitalWrite(LED, HIGH); // sets the LED on
if(DEBUG){Serial.print("connecting... ");}
if (client.connect(hostname, port)) {
if(DEBUG){
Serial.print("connected to ");
Serial.println(hostname);
}
delay(500);
digitalWrite(LED, LOW);
strcpy(line, "GET ");
strcat(line, url);
strcat(line, " HTTP/1.1\r\n");
client.print(line);
if(DEBUG){Serial.print(line);}
strcpy(line, "Host: ");
strcat(line, hostname);
strcat(line, "\r\n");
client.print(line);
if(DEBUG){Serial.print(line);}
strcpy(line, "Authorization: Basic ");
strcat(line, xbmclogon);
strcat(line, "\r\n");
strcat(line, "Connection: close\r\n\r\n");
client.print(line);
delay(500);
if(DEBUG){
Serial.print(line);
while (!client.available());
while (client.available()) {
char c = client.read();
Serial.print(c);
}
Serial.println();
}
client.flush();
delay(200);
if(DEBUG){Serial.println("closing...");}
client.stop();
//digitalWrite(LED, LOW); // sets the LED off
}
else{
digitalWrite(LED, HIGH); // sets the LED on. If always on, last connexion was failed
if(DEBUG){Serial.println("connection failed");}
if (retry > 0) {
retry--;
delay(1000);
runXbmcScript(hostname, port, url, xbmclogon, retry);
}
digitalWrite(LED, LOW);
}
}
void sendToPushingBox(char *serverpbName, char *devid, int retry) {
TCPClient clientx;
char line[255];
clientx.stop();
//digitalWrite(LED, HIGH); // sets the LED on
if(DEBUG){Serial.print("connecting... ");}
if (clientx.connect(serverpbName, 80)) {
if(DEBUG){
Serial.print("connected to ");
Serial.println(serverpbName);
}
delay(500);
digitalWrite(LED, LOW);
strcpy(line, "GET ");
strcat(line, devid);
strcat(line, " HTTP/1.1\r\n");
clientx.print(line);
if(DEBUG){Serial.print(line);}
//delay(1000);
strcpy(line, "Host: ");
strcat(line, serverpbName);
strcat(line, "\r\n");
clientx.print(line);
if(DEBUG){Serial.print(line);}
//delay(1000);
strcpy(line, "Connection: close\r\n");
//strcat(line, "Accept: text/html, text/plain\r\n");
//strcat(line, "Content-Length: 0\r\n");
strcat(line, "User-Agent: Spark\r\n\r\n");
clientx.print(line);
delay(500);
if(DEBUG){
Serial.print(line);
while (!clientx.available());
while (clientx.available()) {
char c = clientx.read();
Serial.print(c);
}
Serial.println();
}
clientx.flush();
delay(200);
if(DEBUG){Serial.println("closing...");}
clientx.stop();
//digitalWrite(LED, LOW); // sets the LED off
}
else{
digitalWrite(LED, HIGH); // sets the LED on. If always on, last connexion was failed
if(DEBUG){Serial.println("connection failed");}
if (retry > 0) {
retry--;
sendToPushingBox(serverpbName, devid, retry);
delay(1000);
}
digitalWrite(LED, LOW);
}
}
void begin_rtttl(char *p)
{
while(*p != ':') p++; // ignore name
p++; // skip ':'
if(*p == 'd')
{
p++; p++; // skip "d="
num = 0;
while(isdigit(*p))
{
num = (num * 10) + (*p++ - '0');
}
if(num > 0) default_dur = num;
p++; // skip comma
}
// get default octave
if(*p == 'o')
{
p++; p++; // skip "o="
num = *p++ - '0';
if(num >= 3 && num <=7) default_oct = num;
p++; // skip comma
}
// get BPM
if(*p == 'b')
{
p++; p++; // skip "b="
num = 0;
while(isdigit(*p))
{
num = (num * 10) + (*p++ - '0');
}
bpm = num;
p++; // skip colon
}
// BPM usually expresses the number of quarter notes per minute
wholenote = (60 * 1000L / bpm) * 2; // this is the time for whole note (in milliseconds)
// Save current song pointer...
songPtr = p;
}
bool next_rtttl() {
char *p = songPtr;
// if notes remain, play next note
if(*p)
{
// first, get note duration, if available
num = 0;
while(isdigit(*p))
{
num = (num * 10) + (*p++ - '0');
}
if(num) duration = wholenote / num;
else duration = wholenote / default_dur; // we will need to check if we are a dotted note after
// now get the note
note = 0;
switch(*p)
{
case 'c':
note = 1;
break;
case 'd':
note = 3;
break;
case 'e':
note = 5;
break;
case 'f':
note = 6;
break;
case 'g':
note = 8;
break;
case 'a':
note = 10;
break;
case 'b':
note = 12;
break;
case 'p':
default:
note = 0;
}
p++;
if(*p == '#') // now, get optional '#' sharp
{
note++;
p++;
}
if(*p == '.') // now, get optional '.' dotted note
{
duration += duration/2;
p++;
}
if(isdigit(*p)) // now, get scale
{
scale = *p - '0';
p++;
}
else {
scale = default_oct;
}
scale += OCTAVE_OFFSET;
if(*p == ',')
p++; // skip comma for next note (or we may be at the end)
songPtr = p; // Save current song pointer...
if(note){ // now play the note
tone(tonePin, notes[(scale - lowest_oct) * 12 + note], duration);
}
else {
delay(duration);
}
return 1; // note played successfully.
}
else {
return 0; // all done
}
}
void tone(int pin, int16_t note, int16_t duration) {
for(int16_t x=0;x<(duration*1000/note);x++) {
PIN_MAP[pin].gpio_peripheral->BSRR = PIN_MAP[pin].gpio_pin; // HIGH
delayMicroseconds(note);
PIN_MAP[pin].gpio_peripheral->BRR = PIN_MAP[pin].gpio_pin; // LOW
delayMicroseconds(note);
}
}
Doorbell STL's
Other Files for 3D printing
#include "application.h"
// XBMC Setup
char xbmcServer[] = "your server"; // XBMC Server
int xbmcPort = 80; // XBMC Port
char xbmcScript[] = "/jsonrpc?request={%22jsonrpc%22:%222.0%22,%22method%22:%22Addons.ExecuteAddon%22,%22params%22:{%22addonid%22:%22script.securitycam%22},%22id%22:%221%22}}"; // Script to run
char xbmcLogon[] = "Base64encoded"; // Username:Password base64 encoded
// Pushing Box Setup
char serverName[] = "api.pushingbox.com"; // Pushingbox Server
char deviceID[] = "/pushingbox?devid=YOURDEVIDHERE"; // Get request
// Select a Tune from below
//char *song = (char *)"The Simpsons:d=4,o=5,b=168:c.6,e6,f#6,8a6,g.6,e6,c6,8a,8f#,8f#,8f#,2g,8p,8p,8f#,8f#,8f#,8g,a#.,8c6,8c6,8c6,c6";
//char *song = (char *)"Indiana:d=4,o=5,b=250:e,8p,8f,8g,8p,1c6,8p.,d,8p,8e,1f,p.,g,8p,8a,8b,8p,1f6,p,a,8p,8b,2c6,2d6,2e6,e,8p,8f,8g,8p,1c6,p,d6,8p,8e6,1f.6,g,8p,8g,e.6,8p,d6,8p,8g,e.6,8p,d6,8p,8g,f.6,8p,e6,8p,8d6,2c6";
//char *song = (char *)"TakeOnMe:d=4,o=4,b=160:8f#5,8f#5,8f#5,8d5,8p,8b,8p,8e5,8p,8e5,8p,8e5,8g#5,8g#5,8a5,8b5,8a5,8a5,8a5,8e5,8p,8d5,8p,8f#5,8p,8f#5,8p,8f#5,8e5,8e5,8f#5,8e5,8f#5,8f#5,8f#5,8d5,8p,8b,8p,8e5,8p,8e5,8p,8e5,8g#5,8g#5,8a5,8b5,8a5,8a5,8a5,8e5,8p,8d5,8p,8f#5,8p,8f#5,8p,8f#5,8e5,8e5";
//char *song = (char *)"Entertainer:d=4,o=5,b=140:8d,8d#,8e,c6,8e,c6,8e,2c.6,8c6,8d6,8d#6,8e6,8c6,8d6,e6,8b,d6,2c6,p,8d,8d#,8e,c6,8e,c6,8e,2c.6,8p,8a,8g,8f#,8a,8c6,e6,8d6,8c6,8a,2d6";
//char *song = (char *)"Muppets:d=4,o=5,b=250:c6,c6,a,b,8a,b,g,p,c6,c6,a,8b,8a,8p,g.,p,e,e,g,f,8e,f,8c6,8c,8d,e,8e,8e,8p,8e,g,2p,c6,c6,a,b,8a,b,g,p,c6,c6,a,8b,a,g.,p,e,e,g,f,8e,f,8c6,8c,8d,e,8e,d,8d,c";
//char *song = (char *)"Xfiles:d=4,o=5,b=125:e,b,a,b,d6,2b.,1p,e,b,a,b,e6,2b.,1p,g6,f#6,e6,d6,e6,2b.,1p,g6,f#6,e6,d6,f#6,2b.,1p,e,b,a,b,d6,2b.,1p,e,b,a,b,e6,2b.,1p,e6,2b.";
//char *song = (char *)"Looney:d=4,o=5,b=140:32p,c6,8f6,8e6,8d6,8c6,a.,8c6,8f6,8e6,8d6,8d#6,e.6,8e6,8e6,8c6,8d6,8c6,8e6,8c6,8d6,8a,8c6,8g,8a#,8a,8f";
//char *song = (char *)"20thCenFox:d=16,o=5,b=140:b,8p,b,b,2b,p,c6,32p,b,32p,c6,32p,b,32p,c6,32p,b,8p,b,b,b,32p,b,32p,b,32p,b,32p,b,32p,b,32p,b,32p,g#,32p,a,32p,b,8p,b,b,2b,4p,8e,8g#,8b,1c#6,8f#,8a,8c#6,1e6,8a,8c#6,8e6,1e6,8b,8g#,8a,2b";
//char *song = (char *)"Bond:d=4,o=5,b=80:32p,16c#6,32d#6,32d#6,16d#6,8d#6,16c#6,16c#6,16c#6,16c#6,32e6,32e6,16e6,8e6,16d#6,16d#6,16d#6,16c#6,32d#6,32d#6,16d#6,8d#6,16c#6,16c#6,16c#6,16c#6,32e6,32e6,16e6,8e6,16d#6,16d6,16c#6,16c#7,c.7,16g#6,16f#6,g#.6";
//char *song = (char *)"MASH:d=8,o=5,b=140:4a,4g,f#,g,p,f#,p,g,p,f#,p,2e.,p,f#,e,4f#,e,f#,p,e,p,4d.,p,f#,4e,d,e,p,d,p,e,p,d,p,2c#.,p,d,c#,4d,c#,d,p,e,p,4f#,p,a,p,4b,a,b,p,a,p,b,p,2a.,4p,a,b,a,4b,a,b,p,2a.,a,4f#,a,b,p,d6,p,4e.6,d6,b,p,a,p,2b";
//char *song = (char *)"StarWars:d=4,o=5,b=45:32p,32f#,32f#,32f#,8b.,8f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32e6,8c#.6,32f#,32f#,32f#,8b.,8f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32e6,8c#6";
//char *song = (char *)"GoodBad:d=4,o=5,b=56:32p,32a#,32d#6,32a#,32d#6,8a#.,16f#.,16g#.,d#,32a#,32d#6,32a#,32d#6,8a#.,16f#.,16g#.,c#6,32a#,32d#6,32a#,32d#6,8a#.,16f#.,32f.,32d#.,c#,32a#,32d#6,32a#,32d#6,8a#.,16g#.,d#";
//char *song = (char *)"TopGun:d=4,o=4,b=31:32p,16c#,16g#,16g#,32f#,32f,32f#,32f,16d#,16d#,32c#,32d#,16f,32d#,32f,16f#,32f,32c#,16f,d#,16c#,16g#,16g#,32f#,32f,32f#,32f,16d#,16d#,32c#,32d#,16f,32d#,32f,16f#,32f,32c#,g#";
//char *song = (char *)"A-Team:d=8,o=5,b=125:4d#6,a#,2d#6,16p,g#,4a#,4d#.,p,16g,16a#,d#6,a#,f6,2d#6,16p,c#.6,16c6,16a#,g#.,2a#";
//char *song = (char *)"Flinstones:d=4,o=5,b=40:32p,16f6,16a#,16a#6,32g6,16f6,16a#.,16f6,32d#6,32d6,32d6,32d#6,32f6,16a#,16c6,d6,16f6,16a#.,16a#6,32g6,16f6,16a#.,32f6,32f6,32d#6,32d6,32d6,32d#6,32f6,16a#,16c6,a#,16a6,16d.6,16a#6,32a6,32a6,32g6,32f#6,32a6,8g6,16g6,16c.6,32a6,32a6,32g6,32g6,32f6,32e6,32g6,8f6,16f6,16a#.,16a#6,32g6,16f6,16a#.,16f6,32d#6,32d6,32d6,32d#6,32f6,16a#,16c.6,32d6,32d#6,32f6,16a#,16c.6,32d6,32d#6,32f6,16a#6,16c7,8a#.6";
//char *song = (char *)"Jeopardy:d=4,o=6,b=125:c,f,c,f5,c,f,2c,c,f,c,f,a.,8g,8f,8e,8d,8c#,c,f,c,f5,c,f,2c,f.,8d,c,a#5,a5,g5,f5,p,d#,g#,d#,g#5,d#,g#,2d#,d#,g#,d#,g#,c.7,8a#,8g#,8g,8f,8e,d#,g#,d#,g#5,d#,g#,2d#,g#.,8f,d#,c#,c,p,a#5,p,g#.5,d#,g#";
char *song = (char *)"Gadget:d=16,o=5,b=50:32d#,32f,32f#,32g#,a#,f#,a,f,g#,f#,32d#,32f,32f#,32g#,a#,d#6,4d6,32d#,32f,32f#,32g#,a#,f#,a,f,g#,f#,8d#";
//char *song = (char *)"Smurfs:d=32,o=5,b=200:4c#6,16p,4f#6,p,16c#6,p,8d#6,p,8b,p,4g#,16p,4c#6,p,16a#,p,8f#,p,8a#,p,4g#,4p,g#,p,a#,p,b,p,c6,p,4c#6,16p,4f#6,p,16c#6,p,8d#6,p,8b,p,4g#,16p,4c#6,p,16a#,p,8b,p,8f,p,4f#";
//char *song = (char *)"MahnaMahna:d=16,o=6,b=125:c#,c.,b5,8a#.5,8f.,4g#,a#,g.,4d#,8p,c#,c.,b5,8a#.5,8f.,g#.,8a#.,4g,8p,c#,c.,b5,8a#.5,8f.,4g#,f,g.,8d#.,f,g.,8d#.,f,8g,8d#.,f,8g,d#,8c,a#5,8d#.,8d#.,4d#,8d#.";
//char *song = (char *)"LeisureSuit:d=16,o=6,b=56:f.5,f#.5,g.5,g#5,32a#5,f5,g#.5,a#.5,32f5,g#5,32a#5,g#5,8c#.,a#5,32c#,a5,a#.5,c#.,32a5,a#5,32c#,d#,8e,c#.,f.,f.,f.,f.,f,32e,d#,8d,a#.5,e,32f,e,32f,c#,d#.,c#";
//char *song = (char *)"MissionImp:d=16,o=6,b=95:32d,32d#,32d,32d#,32d,32d#,32d,32d#,32d,32d,32d#,32e,32f,32f#,32g,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,a#,g,2d,32p,a#,g,2c#,32p,a#,g,2c,a#5,8c,2p,32p,a#5,g5,2f#,32p,a#5,g5,2f,32p,a#5,g5,2e,d#,8d";
//char *song = (char *)"SMBtheme:d=4,o=5,b=100:16e6,16e6,32p,8e6,16c6,8e6,8g6,8p,8g,8p,8c6,16p,8g,16p,8e,16p,8a,8b,16a#,8a,16g.,16e6,16g6,8a6,16f6,8g6,8e6,16c6,16d6,8b,16p,8c6,16p,8g,16p,8e,16p,8a,8b,16a#,8a,16g.,16e6,16g6,8a6,16f6,8g6,8e6,16c6,16d6,8b,8p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16g#,16a,16c6,16p,16a,16c6,16d6,8p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16c7,16p,16c7,16c7,p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16g#,16a,16c6,16p,16a,16c6,16d6,8p,16d#6,8p,16d6,8p,16c6";
//char *song = (char *)"SMBunderground:d=16,o=6,b=100:c,c5,a5,a,a#5,a#,2p,8p,c,c5,a5,a,a#5,a#,2p,8p,f5,f,d5,d,d#5,d#,2p,8p,f5,f,d5,d,d#5,d#,2p,32d#,d,32c#,c,p,d#,p,d,p,g#5,p,g5,p,c#,p,32c,f#,32f,32e,a#,32a,g#,32p,d#,b5,32p,a#5,32p,a5,g#5";
//char *song = (char *)"SMBwater:d=8,o=6,b=225:4d5,4e5,4f#5,4g5,4a5,4a#5,b5,b5,b5,p,b5,p,2b5,p,g5,2e.,2d#.,2e.,p,g5,a5,b5,c,d,2e.,2d#,4f,2e.,2p,p,g5,2d.,2c#.,2d.,p,g5,a5,b5,c,c#,2d.,2g5,4f,2e.,2p,p,g5,2g.,2g.,2g.,4g,4a,p,g,2f.,2f.,2f.,4f,4g,p,f,2e.,4a5,4b5,4f,e,e,4e.,b5,2c.";
//char *song = (char *)"SMBdeath:d=4,o=5,b=90:32c6,32c6,32c6,8p,16b,16f6,16p,16f6,16f.6,16e.6,16d6,16c6,16p,16e,16p,16c";
//char *song = (char *)"RickRoll:d=4,o=5,b=200:8g,8a,8c6,8a,e6,8p,e6,8p,d6.,p,8p,8g,8a,8c6,8a,d6,8p,d6,8p,c6,8b,a.,8g,8a,8c6,8a,2c6,d6,b,a,g.,8p,g,2d6,2c6.,p,8g,8a,8c6,8a,e6,8p,e6,8p,d6.,p,8p,8g,8a,8c6,8a,2g6,b,c6.,8b,a,8g,8a,8c6,8a,2c6,d6,b,a,g.,8p,g,2d6,2c6.";
//char *song = (char *)"2.34kHzBeeps:d=4,o=7,b=240:d,p,d,p,d,p,d,p";
//char *song = (char *)"Satellit:d=8,o=6,b=112:g,e,16f,16e,d,c,g,c7,c";
// Input and Output Pins
int16_t tonePin = D6; //Dorrbell Sound Output
int doorbell = D0; // Doorbell button connects to D0 on the core
int LED = D7; // Built in LED
boolean DEBUG = false; // enable or disable Debug
int Retrys = 5; // Number of times to retry connecting
// RTTTL setup
int notes[] =
{0,
3817,3597,3401,3205,3030,2857,2703,2551,2404,2273,2146,2024,
1908,1805,1701,1608,1515,1433,1351,1276,1205,1136,1073,1012,
956,903,852,804,759,716,676,638,602,568,536,506,
478,451,426,402,379,358,338,319,301,284,268,253,
239,226,213,201,190,179,169,159,151,142,134,127};
#define OCTAVE_OFFSET 0
boolean playing = false;
byte default_dur = 4;
byte default_oct = 6;
byte lowest_oct = 3;
int bpm = 63;
int num;
long wholenote;
long duration;
byte note;
byte scale;
bool songDone = false;
char *songPtr;
unsigned long Lockout; // used to stop flooding servers
void setup() {
pinMode(tonePin,OUTPUT);
pinMode(doorbell, INPUT_PULLUP); // other side of doorbell will connect to ground to pull low
Lockout = millis();
pinMode(LED, OUTPUT); // sets LED as output
if(DEBUG){
digitalWrite(LED,HIGH); // Light the onboard LED so you know it's time to open your Serial Terminal
Serial.begin(9600);
while(!Serial.available()); // wait here for user to press ENTER in Serial Terminal
digitalWrite(LED,LOW);
Serial.print("SSID: ");
Serial.println(Network.SSID());
Serial.print("Core IP: ");
Serial.println(Network.localIP());
Serial.print("Gateway: ");
Serial.println(Network.gatewayIP());
Serial.print("Mask: ");
Serial.println(Network.subnetMask());
Serial.print("WiFi RSSI: ");
Serial.println(Network.RSSI());
}
}
void loop() {
if (millis() >= Lockout){ // check how long its been since last pushed
if(digitalRead(doorbell) == LOW) { //read the doorbell button
delay(50);
if(digitalRead(doorbell) == LOW) { // debounce check again to make sure
Lockout = millis() + 15000; // set up the lockout period 15 seconds before it will run again
RGB.control(true);
RGB.color(0,255,0);
playing = true;
while(playing) {
if(!songDone) { // Start song
songDone = true;
begin_rtttl(song);
}
if(!next_rtttl()) { // Play next note
songDone = false;
playing = false;
delay(2000);
}
}
runXbmcScript(xbmcServer, xbmcPort, xbmcScript, xbmcLogon, Retrys); // opens up a script in xbmc that displays an ip camera
sendToPushingBox(serverName, deviceID, Retrys); // sends push notification to mobile phone or sends email using pushingbox
RGB.control(false);
}
}
}
}
void runXbmcScript(char *hostname, int port, char *url, char *xbmclogon, int retry) {
TCPClient client;
char line[255];
client.stop();
//digitalWrite(LED, HIGH); // sets the LED on
if(DEBUG){Serial.print("connecting... ");}
if (client.connect(hostname, port)) {
if(DEBUG){
Serial.print("connected to ");
Serial.println(hostname);
}
delay(500);
digitalWrite(LED, LOW);
strcpy(line, "GET ");
strcat(line, url);
strcat(line, " HTTP/1.1\r\n");
client.print(line);
if(DEBUG){Serial.print(line);}
strcpy(line, "Host: ");
strcat(line, hostname);
strcat(line, "\r\n");
client.print(line);
if(DEBUG){Serial.print(line);}
strcpy(line, "Authorization: Basic ");
strcat(line, xbmclogon);
strcat(line, "\r\n");
strcat(line, "Connection: close\r\n\r\n");
client.print(line);
delay(500);
if(DEBUG){
Serial.print(line);
while (!client.available());
while (client.available()) {
char c = client.read();
Serial.print(c);
}
Serial.println();
}
client.flush();
delay(200);
if(DEBUG){Serial.println("closing...");}
client.stop();
//digitalWrite(LED, LOW); // sets the LED off
}
else{
digitalWrite(LED, HIGH); // sets the LED on. If always on, last connexion was failed
if(DEBUG){Serial.println("connection failed");}
if (retry > 0) {
retry--;
delay(1000);
runXbmcScript(hostname, port, url, xbmclogon, retry);
}
digitalWrite(LED, LOW);
}
}
void sendToPushingBox(char *serverpbName, char *devid, int retry) {
TCPClient clientx;
char line[255];
clientx.stop();
//digitalWrite(LED, HIGH); // sets the LED on
if(DEBUG){Serial.print("connecting... ");}
if (clientx.connect(serverpbName, 80)) {
if(DEBUG){
Serial.print("connected to ");
Serial.println(serverpbName);
}
delay(500);
digitalWrite(LED, LOW);
strcpy(line, "GET ");
strcat(line, devid);
strcat(line, " HTTP/1.1\r\n");
clientx.print(line);
if(DEBUG){Serial.print(line);}
//delay(1000);
strcpy(line, "Host: ");
strcat(line, serverpbName);
strcat(line, "\r\n");
clientx.print(line);
if(DEBUG){Serial.print(line);}
//delay(1000);
strcpy(line, "Connection: close\r\n");
//strcat(line, "Accept: text/html, text/plain\r\n");
//strcat(line, "Content-Length: 0\r\n");
strcat(line, "User-Agent: Spark\r\n\r\n");
clientx.print(line);
delay(500);
if(DEBUG){
Serial.print(line);
while (!clientx.available());
while (clientx.available()) {
char c = clientx.read();
Serial.print(c);
}
Serial.println();
}
clientx.flush();
delay(200);
if(DEBUG){Serial.println("closing...");}
clientx.stop();
//digitalWrite(LED, LOW); // sets the LED off
}
else{
digitalWrite(LED, HIGH); // sets the LED on. If always on, last connexion was failed
if(DEBUG){Serial.println("connection failed");}
if (retry > 0) {
retry--;
sendToPushingBox(serverpbName, devid, retry);
delay(1000);
}
digitalWrite(LED, LOW);
}
}
void begin_rtttl(char *p)
{
while(*p != ':') p++; // ignore name
p++; // skip ':'
if(*p == 'd')
{
p++; p++; // skip "d="
num = 0;
while(isdigit(*p))
{
num = (num * 10) + (*p++ - '0');
}
if(num > 0) default_dur = num;
p++; // skip comma
}
// get default octave
if(*p == 'o')
{
p++; p++; // skip "o="
num = *p++ - '0';
if(num >= 3 && num <=7) default_oct = num;
p++; // skip comma
}
// get BPM
if(*p == 'b')
{
p++; p++; // skip "b="
num = 0;
while(isdigit(*p))
{
num = (num * 10) + (*p++ - '0');
}
bpm = num;
p++; // skip colon
}
// BPM usually expresses the number of quarter notes per minute
wholenote = (60 * 1000L / bpm) * 2; // this is the time for whole note (in milliseconds)
// Save current song pointer...
songPtr = p;
}
bool next_rtttl() {
char *p = songPtr;
// if notes remain, play next note
if(*p)
{
// first, get note duration, if available
num = 0;
while(isdigit(*p))
{
num = (num * 10) + (*p++ - '0');
}
if(num) duration = wholenote / num;
else duration = wholenote / default_dur; // we will need to check if we are a dotted note after
// now get the note
note = 0;
switch(*p)
{
case 'c':
note = 1;
break;
case 'd':
note = 3;
break;
case 'e':
note = 5;
break;
case 'f':
note = 6;
break;
case 'g':
note = 8;
break;
case 'a':
note = 10;
break;
case 'b':
note = 12;
break;
case 'p':
default:
note = 0;
}
p++;
if(*p == '#') // now, get optional '#' sharp
{
note++;
p++;
}
if(*p == '.') // now, get optional '.' dotted note
{
duration += duration/2;
p++;
}
if(isdigit(*p)) // now, get scale
{
scale = *p - '0';
p++;
}
else {
scale = default_oct;
}
scale += OCTAVE_OFFSET;
if(*p == ',')
p++; // skip comma for next note (or we may be at the end)
songPtr = p; // Save current song pointer...
if(note){ // now play the note
tone(tonePin, notes[(scale - lowest_oct) * 12 + note], duration);
}
else {
delay(duration);
}
return 1; // note played successfully.
}
else {
return 0; // all done
}
}
void tone(int pin, int16_t note, int16_t duration) {
for(int16_t x=0;x<(duration*1000/note);x++) {
PIN_MAP[pin].gpio_peripheral->BSRR = PIN_MAP[pin].gpio_pin; // HIGH
delayMicroseconds(note);
PIN_MAP[pin].gpio_peripheral->BRR = PIN_MAP[pin].gpio_pin; // LOW
delayMicroseconds(note);
}
}
Comments