The driver behind this project is to allow the remote control of some of the equipment in my shed. I have a CNC router/laser cutter that uses my compressor and dust extractor whilst it is running, and well whats the point in having a computer comtrolled machine if you have to hang around and turn the other auxiliary bits on and off?!?
There are a million ways to skin a cat, and the same is true about this project. However after a bit of research I decided the best tool for the job was a Particle Photon. These little micro-processors boards are pretty amazing; they have built in WIFI, 120mhz processor, a language very similar to an Arduino, they are cheap, and the list goes on. But the best part of these processors is actually not what is on the board, they come with a free cloud service that opens up a whole new world including over the air updates, web hooks and lots more. Check out the documentation online for more info.
The key requirements that I started out trying to acheive where;
- Allow manual and remote control of the device (Particle Functions) Allow monitoring of the devices status remotely (Particle Variables) Build a simple web page to display the device status and allow control (Javascript API
And all of that proved to be quite simple!
I then decided to delve into the 'backend' of the cloud services and extended the functionality to also cover;
- Use If This Then That (IFTT) to push the device status changes to my phone (Particle Publish & IFTT recipe) Use IFTT 'Do' to remotely control the device (Do recipe) Use IFTT to log the machine run time (IFTT recipe, google Docs) Use the spreadsheet to calculate the power usage and cummulative run time Email me at the required service intervals (google script)
To create this project I used:
- Particle Photon
- Proto Shield
- Toggle Switch
- 3x LED's with bezels - (you could change this to a single RGB LED)
- Dual opto-isolated relay board
- Standoffs
- A project Box Sheet Alloy 240v Contactor (have a licenced electrician do the work with the contactor An E-Stop Switch 5v wall adaptor Some hookup Wire
Step 1
The first step is to mount everything into the project box. I'm not going to cover this, as your box and hardware is likely different to mine. I will instead focus on the coding and schematic.
Step 2
Claim your particle device and give it a name. Then log into the 'build' environment and start coding your device. The raw code I used is available in the attached text file. You should be able to copy and paste that into the build platform.
Step 3
Verify and flash your device. Then sit back and test it.
Code
SYSTEM_MODE(SEMI_AUTOMATIC); const int Contactor = D7; const int ManualSwitch = D0; const int ConnectedLED = D2; const int AutoLED = D3; const int ManualLED = D4; bool RemoteControl = false; bool ManualOverride = false; unsigned long lastStartStop; void setup() { pinMode(Contactor, OUTPUT); pinSetFast(Contactor); pinMode(ConnectedLED, OUTPUT); tone(ConnectedLED, 20, 0); //start flasshing pinMode(AutoLED, OUTPUT); pinResetFast(AutoLED); pinMode(ManualLED, OUTPUT); pinResetFast(ManualLED); pinMode(ManualSwitch, INPUT_PULLUP); Particle.function("Power", PowerToggle); Particle.variable("RemoteStat", &RemoteControl, BOOLEAN); Particle.variable("ManualStat", &ManualOverride, BOOLEAN); RemoteControl = false; ManualOverride = digitalRead(ManualSwitch); } void loop() { //check wifi status if(Particle.connected()){ tone(ConnectedLED, 1000,0); // stop visually flashing, but flash to save power } else { tone(ConnectedLED, 20,0); // start visually flashing RemoteControl = false; // disconnected from server so fail safe Particle.connect(); // attempt to reconnect waitFor(Particle.connected, 30000); // for max 30 seconds then continue } //check manual override if((digitalRead(ManualSwitch) == LOW) && (ManualOverride == false)){ ManualOverride = true; pinSetFast(ManualLED); Particle.publish("DustExManual","On",5,PRIVATE); } else { if((digitalRead(ManualSwitch) == HIGH) && (ManualOverride == true)) { ManualOverride = false; pinResetFast(ManualLED); Particle.publish("DustExManual","Off",5,PRIVATE); } } //now change the contactor based on the status but only if 15 seconds have elapsed since last change, safety to prevent oscillation or switch bounce if((lastStartStop + 15000) < millis()){ if(RemoteControl == true || ManualOverride == true){ if(digitalRead(Contactor) == HIGH){ digitalWrite(Contactor, LOW); lastStartStop = millis(); } } else { if(digitalRead(Contactor) == LOW){ digitalWrite(Contactor, HIGH); lastStartStop = millis(); } } } } int PowerToggle (String command){ if (command == "on"){ RemoteControl = true; pinSetFast(AutoLED); Particle.publish("DustExRemote","On",60,PRIVATE); return 1; } else if (command == "off"){ RemoteControl = false; pinResetFast(AutoLED); Particle.publish("DustExRemote","Off",60,PRIVATE); return 0; } else if (command == "toggle"){ if(RemoteControl == true){ RemoteControl = false; pinResetFast(AutoLED); Particle.publish("DustExRemote","Off",60,PRIVATE); return 0; } if(RemoteControl == false){ RemoteControl = true; pinSetFast(AutoLED); Particle.publish("DustExRemote","On",60,PRIVATE); return 1; } } else { //unknown command return -1; } }