Software apps and online services
What is a Smart Home without a smart switch for your PC? I wanted to have the option of remotely turning on my PC using any internet-connected device, which would eventually be part of a system that would "initialize home" automatically when I arrive. For this reason I didn't want to use any non-IP network solution (like Bluetooth), but decided to use WiFi in order to connect the smart switch (EspPcSwitch further on) to the internet.
Choosing the WiFi module was easy, the ESP8266 is a no-brainer for WiFi projects, especially since it can be directly programmed using Arduino. I decided to use the WeMos D1 Mini module since it's very easy to work with because of integrated USB-UART and 3V3 regulator, among other things. Of course you could make this project with other ESP versions, there will be some differences depending on specific version (additional 3V3, USB-UART...).
After EspPcSwitch connects to WiFi, the question arises which protocol and platform to use for data transfer? Some free platforms for IoT are available, with complete Android or web apps, but for now I decided to use only the MQTT protocol with a free cloud-based broker. This way I have more flexibility in the future, and I also found it to be more educational. The used MQTT service (CloudMQTT) has a free usage plan (up to 10 connections), which is perfectly fine for this and a couple more projects.
For the user interface/dashboard I used the MQTT Dash Android app, which makes it very easy to create a dashboard on your smartphone with different controls and data reporting.
Below is a basic overview of the whole concept:
*Note: PC image taken from here: http://pngimg.com/download/7722
The final detail that wasn't explained is how to interface to the PC? Well, the answer lies in a small header on the PC motherboard, which in my case (ASRock B85M) looks like this:
This header connects the power button, power LED, HDD activity LED, and reset button from the PC front panel (or wherever your specific PC case has them positioned) to the motherboard electronics. We can easily disconnect the front panel wires from this header and connect our own breadboard, but we can also keep them connected in parallel so we don't interfere with manual switches and the LED that is already on the PC case (this is what I did). For this project I used only the PLED and PWRBTN pins, as described here:
- turning ON/OFF: implemented by connecting to PWRBTN and simulating the power button, which actually connects one signal (+) to ground (GND) for a short time (while pressed). This was done using a NPN transistor as a switch (saturation region), which is easy to connect to a WeMos digital output and control from firmware.
- reading current ON/OFF status: implemented by connecting the base of a NPN transistor to the PLED pin (+). This LED turns on when the PC is on, and off when off. The collector from the NPN goes to a WeMos digital input. This way WeMos is isolated from any voltage that might happen on PLED, and we just pull a small current from the power LED left in parallel in order not to interfere with it.
Note: front panel header pins could have different names in your case, so please check the motherboard documentation when it comes to connecting. In this project I'll refer to the power button connection as PWR SW, and power LED connection as PWR LED, since that's how they are labeled on my PC cables.
Bonus part of the project: I added a DS18B20 1-Wire temperature sensor, because why wouldn't you want to know the temperature inside your PC case? If you don't need this, just don't connect it, the code will work fine.
This concludes the system overview, it's time to set up the environment and build this thing.
First you need to create an account on CloudMQTT. Reading through the short Getting started gives all the needed info, follow the Create a CloudMQTT instance instructions. Basically, we need the Cute Cat free customer plan, and one CloudMQTT instance which gives us all the info to connect to the server (address, port, username, password). After doing this, you should get a Control Panel such as below (instance called EspTest):
After the instance is created, we can click on Details button, which gives us the following:
This overview gives us all the info we need to connect from our Arduino project, but also from our smartphone (we use the same credentials). We'll use it soon enough, for now we just need to know where it is. Also, note the Websocket UI button, which allows us to debug the MQTT connectivity by looking at all received messages, we'll use that later for a first test.
In order to be able to program ESP8266 directly using Arduino IDE, we need to install ESP8266 Arduino core files. I am using Arduino IDE 1.8.1, in which case the installation is done using Arduino Boards Manager, simply follow this procedure (you don't need the older IDE version mentioned there). After following the steps in the link, you should be able to select the WeMos D1 R2 & mini as the board in Arduino IDE:
If you have an older IDE version, or you come across some issues trying to install ESP core files, check out this tutorial.
In order to use MQTT protocol on Arduino, we can use the PubSubClient library, just follow the download link to get the latest zip file. After download, copy the extracted files into the Arduino libraries folder (usually Documents\Arduino\libraries):
If everything went well, you should get the ability to check out PubSub examples in Arduino IDE (File/Examples/PubSubClient).
The additional feature of this project is a DS18B20 sensor measuring the temperature inside the PC case. For this we need to install the OneWire library to get 1-Wire communication, and Dallas Temperature library to handle temperature reading. You need to download both of these (on github you can use option Clone or download/Download ZIP). Extract both libraries to the Arduino libraries folder, the same as we did for PubSubClient. You should now have all the needed libraries:
Note: restart Arduino IDE before trying to compile the project with new libraries, otherwise they might not be recognized if they were just "installed".
The WeMos D1 mini has a micro-USB connector, so we just use a USB cable to connect it to the PC. We can do this now, before starting with the complete hardware build, just to check that everything is fine. Usually Win7/8/10 installs drivers automatically and the module should be recognized as a COM port, but if this fails you can check out the official WeMos webpage for additional info and driver. If everything goes well, you should see a new COM port in Device Manager (on Win10 press Win+X, then M when the list shows).
Now that we have WeMos connected, create a new Arduino sketch and copy to it the project source code. Go to Tools and select the WeMos D1 mini board and the appropriate COM port. In my case it is setup like this:
All you need to do now is insert your WiFi and CloudMQTT credentials into the project, search for the following lines:
#define WIFI_SSID "Your SSID here" #define WIFI_PASS "Your password here" #define CLOUDMQTT_SERVER "m20.cloudmqtt.com" #define CLOUDMQTT_PORT Your port here #define CLOUDMQTT_USER "Your username here" #define CLOUDMQTT_PASS "Your password here"
Note: you won't necessarily get m20.cloudmqtt.com as the server address, insert the one you get on your CloudMQTT Instance details.
After inserting credentials, click on Verify, the code should compile without errors if everything up to this point went well. Open Tools/Serial Monitor so we can start testing (set it to 115200), and click on Upload in the IDE. In a matter of seconds you should get a successful upload and boot info in Serial Monitor:
Note: sometimes you need to restart WeMos (it has a small button) after connecting USB, just try this first if you have problems with upload. Also, you can try to reduce the baudrate (Tools/Upload Speed).
In order to check MQTT transmission, we can go to CloudMQTT Control Panel, click on Details of our instance, then Websocket UI. After resetting WeMos we should get received messages like this:
Don't worry about exact status/temp values at this point, you'll get different values because stuff on the breadboard isn't connected yet. Since we have WeMos programmed and connected, we can now prepare our smartphone dashboard for easier data visualization and debugging. If you didn't get to this point, check Serial Monitor for some debug info, verify that you can connect to WiFi, and then to MQTT.
In order to create our dashboard, first we need to install MQTT Dash from the Play Store. After that, open the app and you should get something like this:
In my case there are two test connections, yours should be empty. Press on the plus sign in the upper right corner and configure the server parameters according to your CloudMQTT instance info (server, port, username, password). Configuration should be something like this:
Don't worry about having a different server address and Client ID, that is normal. Save the configuration by pressing on the Floppy symbol in the upper right corner. You'll get to the previous screen, then press on esppcsw to establish connection. This will be successful if we put in valid credentials, otherwise we'll get a "connection failed" notification. When we have a valid connection to the CloudMQTT server, we can start building up our dashboard. The dashboard created for this project looks like this (yours will be empty):
You can build this up in whatever way you like, I'll go here through the steps for the above dash, and describe functionality of dashboard blocks/buttons.
1. Sync button
This is used to request synchronization of all data from EspPcSwitch. It is useful to get the current status when you run MQTT Dash, otherwise you get old/cached data until EspPcSwitch sends something periodically, which can take a while. By pressing on the plus sign in the upper right corner, we get a menu to configure the type of dashboard block:
For Sync we choose the Switch/button option, and configure it like this:
What we do here is subscribe to esp/pcsw/conn topic, which gives us connection and sync status in textual format. We also enable publishing to esp/pcsw/sync, which will be triggered by pressing the Sync button and will tell our EspPcSwitch that we are requesting fresh data. We need to do one more thing, that is to configure the ON RECEIVE handler like this:
This way our Sync button will be updated as soon as we get anything on the esp/pscw/conn topic (before this happens, we get a spinning progress animation, to show that MQTT Dash is still waiting for a response). Don't forget to click OK and then save the dash block. You should get back to the dashboard screen and see your created Sync button.
This is used to toggle the PC state (on/off). The button alternates between green and red icons depending on state. Start with the plus sign and choose again a Switch/button type block like we did for Sync, configure it as follows:
This text block shows our connection status in textual format. When EspPcSwitch connects to the server, it will show "Connected(x)", where x shows which connection retry this was. When we request sync, it will show "Synced(x)" to show which sync request this was. This way it cannot be mistaken that we have successfully synced data with EspPcSwitch. Create a new dash block, choose Text type and configure as follows:
Shows temperature in °C; create a Text block type like we did for Conn, configure it like this:
After saving this last dash block, you should have all needed dashboard functionality. You can rearrange the blocks to your liking, and later reconfigure if you want them to behave differently. For now, you should run a first connectivity check, by pressing the Sync button (WeMos needs to be powered and connected). You should get refreshed data (note the time info under every dash block), and a "Synced()" message in Conn. If everything works well, it's finally time to start working on the EspPcSwitch hardware.
The schematic description below shows what does what by splitting it into smaller blocks. The full schematic is in the attachments area, you could skip this part if you are sure you know what you are doing.
PWR SW block (going from WeMos pin D6):
This part of the schematic handles power button emulation. The D6 pin is configured as output, and it has a 2k2 pulldown (R1) in order to prevent triggering the transistor Q1 during ESP boot. LED1 and R2 are just to see if everything works fine, you don't necessarily have to use them. Resistor R3 connects to base of NPN transistor Q1, and it should give something around 1 mA base current (take 3V3 from pin, remove a rough 1 V for Q1 BE junction, you get around 2 V on R3). This 1 mA will be perfectly fine to keep Q1 saturated for anything we need to pull to ground (on my PC I measured only 0.5 mA when the PWR SW is pressed, but I'm not sure if this is universal). Resistor R4 is to protect the transistor from too much current if we connect it somewhere it shouldn't be connected (like 5 V power rail). This is just a personal preference and security measure, you can completely ommit R4, or reduce it's value if it gives you any trouble (like if the PC doesn't react to our toggling of Q1). Finally, headers J1 and J2 are to connect the power button from your PC case, and the motherboard header where the button was previously connected (doesn't matter which goes where). This way we can act like the power button, but still keep the manual button functionality. Take care of polarity markings: it won't work if you connect it wrong (nothing bad should happen though). Any ground connection here (to J1/J2) was ommited on purpose, we should already have the ground connection from USB cable, and no ground loops are wanted :).
PWR LED block (going from WeMos pin D5):
This part of the schematic gets PC status from the PWR LED. The D5 pin is configured as input, so for this description we'll start from the right side of the schematic, since it is also the direction of the signal. On J3/J4 we connect the PC power LED from front panel, and in parallel we likewise connect to motherboard pins for this LED. This way the PC LED behaves as usually, and we also "steal" a small bit of current from it to get it's status (on/off). This status signal goes through R8 to the base of Q2. Depending on the PWR LED, we should get somewhere in the range of 0.5 mA of base current (for a 2 V LED, taking away 1 V for BE junction, leaves us 1 V on R8) which would be perfectly fine for tens of mA on the collector side. We have R10 in order to pull-down the Q2 base when there is no signal available (to have a stable off state). The collector of Q2 is pulled up with R7, and it also has LED2 + R9 for testing purposes (it will work without the last two). The final connection to ESP input pin is through R6, just to limit the ESP current if we mess something up in firmware. So, what happens here is that by using Q2 we have inverted our status signal: when PWR LED is on, we get zero on pin D5 because Q2 is conducting (saturated state) and there is basically 0 V at it's collector (for small currents like we have). When PWR LED is off, we get 3V3 on pin D5 (for this the R7 pull-up is important). We'll handle this inversion easily in firmware. Note that LED2 will give us the right status - it will be turned on at the same time when PWR LED is on.
Note: if you are wondering why I used relatively large resistors (6k8) in series with LED1 and LED2, it's because my LED's were of the ultra-bright sort, and at 10 mA they seem more like lasers when looked at directly. Adjust the resistors as you like, but be careful not to overload ESP8266 outputs (12 mA max).
So, that's it for the schematic part. The full version in attachment has the DS18B20 temperature sensor connected to get temperature readings inside our PC case. This is trivial because it needs only three connections and one pull-up, so it won't be described separately. Except one small note: the pull-up (R5) is 6k8, instead of the usual 4k7 for 1-Wire, because on WeMos pin D3 there is already a 10k pull-up so it was accounted for this way (probably not really important though).
Following the schematic, now we connect everything on the breadboard. You could connect it like this:
Crucial points to take away:
- the power comes from WeMos 3V3 regulator, which is powered by the USB port
- Q1 and Q2 NPN transistors (BC337) have CBE pinout (collector is pin 1). If your transistor is EBC, turn it around 180 degrees. You could make this project work with almost any generic NPN.
- J1 and J2 are where we'll connect the power button from PC case and the motherboard PWR SW pins (doesn't matter which goes where). Take care of the polarity, check your motherboard documentation. The ground connection (-) wasn't connected to our breadboard ground because it doesn't need to be, we get it from USB.
- J3 and J4 are where we'll connect the PWR LED pins from our motherboard and the PC case LED, watch the polarity. As with J1/J2, breadboard ground wasn't connected with "-" on the connector.
- all headers (J1, J2, J3, J4) are here for convenience. You could just use jumper wires to connect to these pins on the breadboard. If using headers like this, you will most likely have to wiggle the header plastic to the middle of the pin (or remove it completely), otherwise it won't connect well.
At this point it would be very wise to connect EspPcSwitch to the PC (USB only) and check with Arduino Serial Monitor and MQTT Dash that everything works well. We should get valid temperature readings if our 1-Wire sensor is connected properly. Our PC state on MQTT Dash should be off (red). By pressing the State button on the dashboard we should see LED1 turn on for a fraction of a second (300 ms). By connecting 3V3 from the breadboard to J3 connector (+), our LED2 should turn on and we should get PC state ON (green). If this test passes, we are ready to connect EspPcSwitch to the PC.
Until now we were simply using USB power from the PC to power the EspPcSwitch. The main thing we need to think about now is that we want power to be available even when the PC is turned off. Many motherboards today support USB charging when off, in which case we can just leave everything connected to the USB port and be done with it. This is exactly how it works on my system (ASRock B85M motherboard + Windows 10). In order to check if your motherboard supports this, just turn off your PC and see if you have MQTT connectivity to EspPcSwitch. If so, you are lucky and it will work as planned. If not, check your motherboard documentation to see if it can be enabled, or go with the second option: connecting EspPcSwitch to a USB phone charger. Below is a description of both options.
Update (18.4.2017.): I noticed that USB power during "shutdown" actually seems to be a manifestation of the Win 10 hybrid shutdown feature that is active by default on my system. If you have this disabled then you most likely won't have power on USB ports during shutdown. This means that if you need EspPcSwitch to be more reliable and universal, I'd recommend powering it from a USB charger, since this is a generic approach that should work on any system. I'm still going with the motherboard powered option and it's working fine on my system, except in rare cases such as force-shutdown which turns everything off (in which case I'm by the PC anyway so it's not an issue).
Power supply options:
- Powered from motherboard: You can just leave EspPcSwitch connected to any USB port giving power when the PC is off. If you want to make everything tidy and closed in the PC case, a USB 2.0 motherboard adapter cable can be used, which connects directly to the motherboard USB header and gives you USB connectors on the other side. Check out your motherboard documentation for details where to connect.
- Powered from USB charger: You can use basically any generic 5 V smartphone charger with USB output. Of course I cannot guarantee that all will work, but if it's got 0.5 A and more it should be fine, simply connect to verify. By connecting our board to a charger we will lose the ground (GND) connection with PC that we would have if we connected directly to the PC USB port. It is crucial to fix this, and it can be done by connecting the J1/J2 GND (-) pin to the breadboard GND (this was done by the added jumper wire on the picture below).
Now that you have figured out what to use as a power supply, turn everything off, including your PC! It is time to connect our breadboard connectors J1, J2, J3, J4 to the PC. For this you need to find the front panel header on your motherboard (check out the documentation), in my case it has the following pinout:
Connection procedure according to the above pinout:
- unplug wires PWRBTN# (this is actually "+") and the GND pin ("-") coming from the front panel to the header, and connect them to our J2
- take two Dupont wires and connect them from our J1 to the motherboard header pins PWRBTN# and GND
- unplug wires PLED+ and PLED- coming from the front panel to the header, and connect them to our J4
- take two Dupont wires and connect them from our J3 to the motherboard header pins PLED+ and PLED-
Double-check the connections and power up the EspPcSwitch. It should connect to CloudMQTT and be visible on our Android dashboard. Now you can try to turn on the PC using the dashboard, LED1 should blink when you press the State dashboard button. One more step potentially awaits you now, that is to check if Windows Power Options are configured properly. More info in the next chapter.
In order to be able to turn the PC off by pressing the power button, you have to select the appropriate setting in Windows Power Options. On Windows 7 and newer OSes you can press the Win keyboard button, type Power Options in the search box and open it from there. On Win10 you can also use Win+X shortcut and select Power Options in the list that shows. The last possibility is to find it manually in the Control Panel. In any case, you should get something like this (Win10):
Now we need to select "Choose what the power buttons do", and we get this window:
Here you can decide what the power button does. I prefer having it on Hibernate in order for the PC to save its state if I turn it off remotely. You can use that or Shut down, or any other option you find appropriate for your system.
At this point you should have everything setup and well tested already. EspPcSwitch should be connected to the PC and running, MQTT Dash active on the smartphone, and by pressing Sync on the dashboard you should get refreshed data. It's time to save anything you might have active on your PC and try turning the PC off and on. MQTT Dash should perfectly reflect (with only a couple seconds delay) the PC status, or to be more precise: the status of the PC power LED. Also, verify that your manual power button and LED still work normally.
Good luck and have fun! If you have any ideas for improvements, please leave a comment. I'm also curious about cool IoT platforms and apps, so if you have any recommendations for this and other projects, I'm listening.
Update (1.5.2017.): Got across a situation where EspPcSwitch was unavailable, regardless of Wifi and CloudMQTT being perfectly fine. Found out it was stuck in "Attempting MQTT connection...", in the Mqtt_Reconnect() function. I didn't research what exactly got messed up (Wifi, PubSubClient...), but implemented a simple workaround: the ESP8266 is now restarted if we are in the Mqtt_Reconnect() function for more than two minutes. A restart seems to fix this issue easily.