Hardware components | ||||||
| × | 1 | ||||
| × | 1 | ||||
Software apps and online services | ||||||
|
This is my first post, but surely not the last.
IdeationA few weeks ago, I requested a stand-up desk due to the amount of time I spend while seating and working from Stand Desks.
But I was beginning to be annoyed by the fact that I had to migrate my desktop every time I stand up or sit, this gave me an innovative idea of using the tools and skills I have.
By attaching an ultrasonic sensor to my Stand Desk, I can be able to detect if I am standing or not.
This is How It WorksAssuming you feel like working while standing up, the moment you are within a range of 2-50cm distance from your monitor, this will send an MQTT message to an MQTT broker running on the laptop (Workstation) which will execute a bash script responsible for managing multiple monitors.
The NodeMCU Arduino code is a bit complicated but I will try to uncomplicate it. Instead of hardcoding WiFi credentials (SSID's and Passwords), I opted to use WiFiManager library by Tzapu, I will not go into detail about it. I also used ArduinoOTA for Over-The-Air flashing, MQTT libraries and also ESP8266 Ping library for pinging hosts.
The LaptopFor my laptop, I installed PahoMQTT and Pynotify - for popup notifications. The code is pretty much straight forward and self explanatory.
From here, the only thing left is just to Cronjob proximity.py on your local laptop, edit Arduino code with your MQTT broker ip address, and it should automagically work.
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <ArduinoOTA.h>
//needed for library
#include <DNSServer.h>
#include <ESP8266WebServer.h>
//https://github.com/tzapu/WiFiManager
#include <WiFiManager.h>
//https://github.com/dancol90/ESP8266Ping
#include <ESP8266Ping.h>
#include <PubSubClient.h>
// https://github.com/MajenkoLibraries/Average
#include <Average.h>
#include<stdlib.h>
#define Hostname "stand-up-desk-proximity-sensor"
#define MasterPass "ESP8266"
#define OTAPort 8266
//"alexapi"
//#define mqtt_server_1 "192.168.1.232"
#define mqtt_server_1 "192.168.1.232"
#define mqtt_topic "work/proximity"
#define mqtt_port 1883
// Define NodeMCU D5 pin to as temperature data pin of DHT11
#define ECHO D1
#define TRIGGER D2
#define Statusled D3
#define WiFiLed D5
// #define Reset_Button D6
// Define macros
#define Between(x, a, b) (((a) <= (x)) && ((x) <= (b)))
#define Outside(x, a, b) (((x) < (a)) || ((b) < (x)))
#define LessOrEqual(x, y) ((x) <= (y))
#define MoreOrEqual(x, y) ((x) >= (y))
// Variables
// Reserve space for 10 entries in the average bucket.
Average<float> ave_distance(10);
int count = 0;
int wifiCount = 0;
int sleep = 50;
int wifi_reset = 0;
int Samples = 50;
int maximumRange = 200; // Maximum range
int minimumRange = 2; // Minimum range
float prohibitedDistance = 60.0; // Distance Alarm will be sounded
// long lastMsg = 0;
char msg[50];
char message[65];
WiFiClient espClient;
PubSubClient client(espClient);
void setup() {
Serial.begin(115200);
setup_GPIO();
setup_OTA();
setup_WiFi();
setup_MQTT();
}
void setup_GPIO(){
pinMode(TRIGGER, OUTPUT);
pinMode(ECHO, INPUT);
pinMode(WiFiLed, OUTPUT);
pinMode(Statusled, OUTPUT);
}
void setup_OTA() {
// Port defaults to 8266
ArduinoOTA.setPort(OTAPort);
// Hostname to Temp_Hum_Sensor-01
ArduinoOTA.setHostname(Hostname);
// Enable authentication
ArduinoOTA.setPassword(MasterPass);
ArduinoOTA.onStart([]() {
Serial.println("Start OTA");
});
ArduinoOTA.onEnd([]() {
Serial.println("End OTA");
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\n", (progress / (total / 100)));
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
else if (error == OTA_END_ERROR) Serial.println("End Failed");
});
ArduinoOTA.begin();
}
void setup_WiFi() {
// Connect to WiFi access point.
WiFiManager wifiManager;
Serial.print("WiFi Reset status: ");
Serial.println(wifi_reset);
if (wifi_reset == 1) {
//reset settings - assign a button for this.
wifiManager.resetSettings();
wifi_reset = 0;
}
//sets timeout until configuration portal gets turned off
//useful to make it all retry or go to sleep
//in seconds
wifiManager.setTimeout(180);
// Connect to WiFi access point.
if (!wifiManager.autoConnect(Hostname, MasterPass)) {
Serial.println("failed to connect, we should reset as see if it connects");
delay(3000);
ESP.restart();
delay(5000);
}
delay(50);
Serial.println();
Serial.print("Connecting to WiFi access point: ");
//Serial.println(ssid_1);
Serial.print("Connecting.");
while (WiFi.status() != WL_CONNECTED) {
digitalWrite(WiFiLed, HIGH);
delay(50);
digitalWrite(WiFiLed, LOW);
delay(50);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
digitalWrite(WiFiLed, HIGH);
Serial.print("MAC Address: ");
Serial.println(WiFi.macAddress());
Serial.println();
}
void setup_MQTT(){
delay(10);
Serial.print("Connecting to MQTT Server: ");
Serial.println(mqtt_server_1);
client.setServer(mqtt_server_1, mqtt_port);
}
void reconnect() {
Serial.println();
Serial.print("Pinging MQTT BrokerIP: ");
Serial.print(mqtt_server_1);
if(Ping.ping(mqtt_server_1)){
Serial.println(" Ok!!!");
// Loop until we"re reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Create a random client ID
String clientId = "ESP8266Client-";
clientId += String(random(0xffff), HEX);
// Attempt to connect
//if you MQTT broker has clientID,username and password_1
//please change following line to if (client.connect(clientId, userName, password_1))
if (client.connect(clientId.c_str())){
Serial.println("connected...");
Serial.print("and subscribe to topic: ");
Serial.println(mqtt_topic);
//once connected to MQTT broker, subscribe command if any
client.subscribe(mqtt_topic);
}else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
else if (WiFi.status() != 3) {
Serial.println("");
Serial.println("WiFi disconnects, reconnecting.");
wifi_reset = 1;
delay(1000);
ESP.restart();
delay(3000);
Serial.print("WiFi Reset status: ");
Serial.print(wifi_reset);
setup_WiFi();
}
else {
Serial.println();
Serial.print(":Failed to establish a connection on MQTT Broker.");
delay(1000);
ESP.restart();
delay(1000);
}//end reconnect()
}
float Proximity(){
//delay(10);
float duration, distance;
digitalWrite(TRIGGER, LOW);
delayMicroseconds(2);
digitalWrite(TRIGGER, HIGH);
delayMicroseconds(10);
digitalWrite(TRIGGER, LOW);
duration = pulseIn(ECHO, HIGH);
//Serial.print(duration);
distance = duration / 58.0;
//Serial.print(distance);
return distance;
}
// For Debug
// void loop(){
// float raw_distance;
// raw_distance = Proximity();
// Serial.print("Raw distance: ");
// Serial.println(raw_distance);
// delay(1000);
// }
void loop() {
ArduinoOTA.handle();
if (!client.connected()){
reconnect();
}
client.loop();
delay(10);
float raw_distance, distance;
raw_distance = Proximity();
//Serial.print("Raw distance: ");
//Serial.println(raw_distance);
ave_distance.push(raw_distance);
// calculate the average of samples
for(int i = 0; i < Samples; i++){
ave_distance.get(i);
}
count += 1;
if(count > Samples){
count = 0;
distance = ave_distance.mean();
//Serial.print("Current Distance (CM)");
//Serial.println(distance);
if (Between(distance, minimumRange, maximumRange) && LessOrEqual(distance, prohibitedDistance)){
Serial.println("You are standing up, moving to Monitor#2!!!!");
String msg = "Distance (Cm): ";
msg = msg + distance;
msg.toCharArray(message, 65);
Serial.println(message);
client.publish(mqtt_topic, "1");
delay(500);
}
else{
Serial.println("You possibly seating!!!!");
Serial.print("Distance (Cm): ");
Serial.println(distance);
client.publish(mqtt_topic, "0");
}
if Outside(distance, minimumRange, maximumRange){
Serial.println("Invalid range. Range set to 2-200cm");
}
/*
if LessOrEqual(distance, prohibitedDistance){
Serial.println("You are standing up, moving to Monitor#2!!!!");
digitalWrite(Statusled, HIGH);
delay(1000);
}
else{
Serial.println("You possibly not standing up, staying on Monitor#1!!!!");
digitalWrite(Statusled, LOW);
}*/
}
}
#!/usr/bin/python
import paho.mqtt.subscribe as subscribe
import subprocess
import time
import pynotify
mqtt_topic = 'work/proximity'
notified = False
def sendmessage(title, message):
pynotify.init("Basic")
notice = pynotify.Notification(title, message)
notice.show()
while True:
msg = subscribe.simple(mqtt_topic)
value = float(msg.payload)
if value == 0:
if not notified:
title = '...Seating...'
message = 'Moving your desktop and windows over.'
sendmessage(title, message)
time.sleep(0.5)
subprocess.call(["$HOME/bin/seating"])
notified = True
else:
if notified:
title = '...Standing...'
message = 'Moving your desktop and windows over.'
sendmessage(title, message)
time.sleep(0.5)
subprocess.call(["$HOME/bin/standing"])
notified = False
time.sleep(1)
#!/bin/bash
xrandr --auto --output HDMI2 --off --output HDMI1 --off --output DP1 --above eDP1 --mode 1920x1200 --pos 1920x0 --rotate normal --output eDP1 --mode 1920x1080 --pos 0x88 --rotate normal --output VIRTUAL1 --off
Comments