Testing my 10gbps fiber
If your mobile doesn’t have a filter, you should be able to see fiber connections using camera.
Tag Archives: hardware
Hex Dimmer
Control a dimmer using a hex wireless box.
Parts
- Wemos Mini
- MPU6050 – Gyroscope Module
- 10k Resistor
- TP4056 – Battery Charger Module
- Mini Battery
- Wireless Charger
Put the box flat on the table to switch off.
When you put it on one side, it will controll your lights brightness.
20,40,60,80 and 100%, just by rotating and putting it down on its sides.
Schematics (without the wireless charging part)
Node-Red Controll part (source below)
Nice to have’s :
Arduino-sleep mode, wakeup with a movement sensor.
Arduino Code
#include <Wire.h>
//#include <SPI.h>
#include <PubSubClient.h>
//#include <string.h>
//#include <stdio.h>
#include <ESP8266WiFi.h>
// Wifi settings
const char* ssid = "xxxxxx";
const char* password = "xxxxxxxxxx";
const char* mqtt_server = "10.1.0.17";
// I2C address of the MPU-6050 - 0x68 or 0x69 if AD0 is pulled HIGH
const int MPU = 0x68;
int16_t AcX, AcY, AcZ, GyX, GyY, GyZ;
float gForceX, gForceY, gForceZ, rotX, rotY, rotZ;
// Wifi MAC address
byte mac[]= { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
WiFiClient espClient;
IPAddress ip;
PubSubClient mqttClient(espClient);
// IP address of your MQTT server
const char* server = "10.1.0.17";
//const char* outTopic = "test/";
//const char* server = "iot.eclipse.org";
void dataReceiver(){
Wire.beginTransmission(MPU);
Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU,14,true); // request a total of 14 registers
AcX = Wire.read()<<8|Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
AcY = Wire.read()<<8|Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
AcZ = Wire.read()<<8|Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
GyX = Wire.read()<<8|Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
GyY = Wire.read()<<8|Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
GyZ = Wire.read()<<8|Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
processData();
}
void processData(){
gForceX = AcX / 16384.0;
gForceY = AcY / 16384.0;
gForceZ = AcZ / 16384.0;
rotX = GyX / 131.0;
rotY = GyY / 131.0;
rotZ = GyZ / 131.0;
}
void debugFunction(int16_t AcX, int16_t AcY, int16_t AcZ, int16_t GyX, int16_t GyY, int16_t GyZ){
// Print the MPU values to the serial monitor
Serial.print("Accelerometer: ");
Serial.print("X="); Serial.print(gForceX);
Serial.print("|Y="); Serial.print(gForceY);
Serial.print("|Z="); Serial.println(gForceZ);
Serial.print("Gyroscope:");
Serial.print("X="); Serial.print(rotX);
Serial.print("|Y="); Serial.print(rotY);
Serial.print("|Z="); Serial.println(rotZ);
}
void reconnect() {
// Loop until we're reconnected
while (!mqttClient.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (mqttClient.connect("arduinoClient")){
Serial.println("connected");
}
else {
Serial.print("failed, rc=");
Serial.print(mqttClient.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(1000);
}
}
}
void setup(){
Serial.begin(9600);
setup_wifi();
Wire.begin(0,2);
Wire.beginTransmission(MPU);
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);
mqttClient.setServer(server, 1883);
// Ethernet.begin(mac);
// ip = Ethernet.localIP();
Serial.println(ip);
Serial.println(server);
//delay(1500);
}
char* init(float val){
char buff[100];
for (int i = 0; i < 100; i++) {
dtostrf(val, 4, 2, buff); //4 is mininum width, 6 is precision
}
return buff;
}
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void dataAcc(){
char mpu6050X[100]= "";
strcat(mpu6050X,init(gForceX));
char mpu6050Y[100]= "";
strcat(mpu6050Y,init(gForceY));
char mpu6050Z[100]= "";
strcat(mpu6050Z,init(gForceZ));
// accelerometer - "topic, mpu6050"
mqttClient.publish("AcX/", mpu6050X);
mqttClient.publish("AcY/", mpu6050Y);
mqttClient.publish("AcZ/", mpu6050Z);
// mqttClient.publish(outTopic, "text to send via mqtt");
}
void dataGy(){
char mpu6050X[100]= "";
strcat(mpu6050X,init(rotX));
char mpu6050Y[100]= "";
strcat(mpu6050Y,init(rotY));
char mpu6050Z[100]= "";
strcat(mpu6050Z,init(rotZ));
// gyroscope - "topic, mpu6050"
mqttClient.publish("GyX/", mpu6050X);
mqttClient.publish("GyY/", mpu6050Y);
mqttClient.publish("GyZ/", mpu6050Z);
// mqttClient.publish(outTopic, "text to send via mqtt");
}
void loop(){
dataReceiver();
debugFunction(AcX,AcY,AcZ,GyX,GyY,GyZ);
if (!mqttClient.connected()) {
reconnect();
}
mqttClient.loop();
dataAcc();
dataGy();
delay(2000);
}
Nodered Flow
[
{
"id": "7550958a.b29dec",
"type": "mqtt in",
"z": "a0126a6a.9c70b8",
"name": "",
"topic": "hex/x",
"qos": "2",
"broker": "8c74c5f6.9a7a48",
"x": 270,
"y": 100,
"wires": [
[
"d251dd79.5700d"
]
]
},
{
"id": "e84b0a1.18096f8",
"type": "mqtt in",
"z": "a0126a6a.9c70b8",
"name": "",
"topic": "hex/y",
"qos": "2",
"broker": "8c74c5f6.9a7a48",
"x": 270,
"y": 180,
"wires": [
[
"9c27bc8f.b62dd"
]
]
},
{
"id": "6a1a0d8d.b3e754",
"type": "mqtt in",
"z": "a0126a6a.9c70b8",
"name": "",
"topic": "hex/z",
"qos": "2",
"broker": "8c74c5f6.9a7a48",
"x": 270,
"y": 260,
"wires": [
[]
]
},
{
"id": "2d2a911a.6af3fe",
"type": "ui_gauge",
"z": "a0126a6a.9c70b8",
"name": "",
"group": "d43a9f25.6c874",
"order": 23,
"width": 0,
"height": 0,
"gtype": "gage",
"title": "gauge",
"label": "units",
"format": "{{value}}",
"min": "0",
"max": "100",
"colors": [
"#00b500",
"#e6e600",
"#ca3838"
],
"seg1": "",
"seg2": "",
"x": 1010,
"y": 120,
"wires": []
},
{
"id": "d251dd79.5700d",
"type": "function",
"z": "a0126a6a.9c70b8",
"name": "Get level from box",
"func": "var my=msg.payload;\nmsg.payload = {};\nif (my == 0.85){\n msg.payload=20;\n return msg;\n}\nelse if (my == 0.86){\n msg.payload=20;\n return msg;\n}\nelse if (my == 0.87){\n msg.payload=20;\n return msg;\n}\n\nelse if (my == 0.03){\n msg.payload=40;\n return msg;\n}\nelse if (my == 0.02){\n msg.payload=40;\n return msg;\n}\n\nelse if (my == 3.17){\n msg.payload=60;\n return msg;\n}\nelse if (my == 3.18){\n msg.payload=60;\n return msg;\n}\n\nelse if (my == 0.04){\n msg.payload=80;\n return msg;\n}\nelse if (my == 0.05){\n msg.payload=80;\n return msg;\n}\n\nelse if (my == 3.95){\n msg.payload=100;\n return msg;\n}\nelse if (my == 3.96){\n msg.payload=100;\n return msg;\n}\nelse {\n return msg;\n \n}\n",
"outputs": 1,
"noerr": 0,
"x": 510,
"y": 120,
"wires": [
[
"ecd746cc.fce348",
"8721e902.45d8b8",
"39c8f1ac.86affe"
]
]
},
{
"id": "39c8f1ac.86affe",
"type": "function",
"z": "a0126a6a.9c70b8",
"name": "Set Living spots level (idx 5)",
"func": "var level = Number(msg.payload);\nmsg.payload = {};\nmsg.payload.idx = 5;\nmsg.payload.switchcmd = (\"Set Level\");\nmsg.payload.command = \"switchlight\";\nmsg.payload.level = level;\nreturn msg; ",
"outputs": 1,
"noerr": 0,
"x": 820,
"y": 260,
"wires": [
[
"bc0d6507.1d7748"
]
]
},
{
"id": "bc0d6507.1d7748",
"type": "mqtt out",
"z": "a0126a6a.9c70b8",
"name": "",
"topic": "domoticz/in",
"qos": "",
"retain": "",
"broker": "8c74c5f6.9a7a48",
"x": 1080,
"y": 260,
"wires": []
},
{
"id": "9c27bc8f.b62dd",
"type": "function",
"z": "a0126a6a.9c70b8",
"name": "Flat or standing up",
"func": "var mya=msg.payload;\nmsg.payload = {};\nif (mya < -3.80){\n flow.set(\"levely\",1);\n msg.payload = \"plat\";\n }\nelse {\n flow.set(\"levely\",2);\n msg.payload = \"rechtop\";\n}\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 450,
"y": 200,
"wires": [
[
"ecd746cc.fce348"
]
]
},
{
"id": "ecd746cc.fce348",
"type": "debug",
"z": "a0126a6a.9c70b8",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"x": 640,
"y": 340,
"wires": []
},
{
"id": "8721e902.45d8b8",
"type": "function",
"z": "a0126a6a.9c70b8",
"name": "Gate for level ",
"func": "\nvar x = msg.payload;\ny = flow.get(msg.payload);\nvar y = flow.get('levely') || 0;\n\nif (y == 1){\n msg.payload = {};\n msg.payload = 0;\n} else {\n msg.payload = x;\n}\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 810,
"y": 120,
"wires": [
[
"2d2a911a.6af3fe",
"da72437e.88376"
]
]
},
{
"id": "da72437e.88376",
"type": "debug",
"z": "a0126a6a.9c70b8",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"x": 890,
"y": 200,
"wires": []
},
{
"id": "8c74c5f6.9a7a48",
"type": "mqtt-broker",
"z": "",
"name": "10.1.0.17",
"broker": "10.1.0.17",
"port": "1883",
"clientid": "",
"usetls": false,
"compatmode": true,
"keepalive": "15",
"cleansession": true,
"birthTopic": "",
"birthQos": "0",
"birthPayload": "",
"closeTopic": "",
"closePayload": "",
"willTopic": "",
"willQos": "0",
"willPayload": ""
},
{
"id": "d43a9f25.6c874",
"type": "ui_group",
"z": "",
"name": "Control",
"tab": "739541e2.18396",
"order": 1,
"disp": true,
"width": "6",
"collapse": false
},
{
"id": "739541e2.18396",
"type": "ui_tab",
"z": "",
"name": "7inch",
"icon": "dashboard",
"order": 1,
"disabled": false,
"hidden": false
}
]
Broken or slow laptop? Screen still works?
Remove the screen and check its connector.
Maybe you can buy a controller board in china for cheap.
I took apart a EEEpc with a nice little screen.
I looked for HSD100IFW1-A00 1024-600 controller.
And ordered a
Driver Board for 10.1 “HSD100IFW1-A00/HSD100IFW1-A04 / HSD100IFW1 Lcd Composite + Tv(RF) + Usb + Vga + Hdmi-Compatibel 1024 × 600 Controller Board
It was only around 20 euro’s.


Safe fireworks this year
This year i used safe fireworks.
A ledstrip ( about 600 leds ) controlled by an arduino.
Only problem is .. there is no sound, but i managed to fix that 🙂
Mikrotik
Switches and access-points
Today i got my RB4011 ! Wooot!
Total tally
- MikroTik CRS305-1G-4S+IN – Lab
- MikroTik RB2011UiAS-RM – Office
- MikroTik hAP AC2 – Studio
- MikroTik CRS109-8G-1S-2HnD-IN – Attic
- MikroTik RB4011iGS+5HacQ2HnD-IN – Livingroom
- NEW (2022-04-02) crs125-24g-1s-in (2022-04-02)
To replace .. 4 SLM2008 and a TPLink switch 🙂

I’ll be posting something about connecting an arduino to the serial console using a tcp server later.
Mikrotiks are all you can eat .. And there is a lot of functionality. One of the main features (besides being switches and routers)
- Openvpn server
- DIY display connect
- Proxy
- Today Vincent mentioned Mqtt plugin (2022-apr-6)
- https://help.mikrotik.com/docs/display/ROS/Packet+Sniffer sounds interesting also
Installing extra packages
- Download correct package zip from ( https://mikrotik.com/download )
- Extract and use file upload
- Reboot your mikrotik
Action LSC Alarm/Siren
Update 20221208 – removed internals

I’ve modded several LSC devices, most of them i could flash with esp-easy or tasmota.
Why mod it? Because it uses the cloud .. i’d like to keep control myself.
Just connect/solder a USB to TTL Converter UART Module like below.
(See other posts)

But this alarm was different, i ended up removing the chip and replace it with a ESP12.

So now i had to figure out which GPIO pins and how to control them.
#1/bin/bash
# Flashed ESP Easy on this one
# When i did this, 2019, you needed version 2.1-beta1
# GPIO 4 controls LED
sleep 10
curl http://10.1.1.251/control?cmd=GPIO,4,1
sleep 1
curl http://10.1.1.251/control?cmd=GPIO,4,0
sleep 1
curl http://10.1.1.251/control?cmd=GPIO,4,1
sleep 2
curl http://10.1.1.251/control?cmd=GPIO,4,0
sleep 5
# Sending rtttl ringtone
curl "http://10.1.1.251/control?cmd=rtttl,5:d=4,o=5,b=112:8a,8a,a,8a,8a,a,8a,8c6,8f.,16g,2a,8a-,8a-,8a-.,16a-,8a-,8a,8a.,16a,8a,8g,8g,8a,g,c6"
alarm sound
curl "http://10.1.1.251/control?cmd=rtttl,5:d=4,o=5,b=160:2g,2c6,2g,2c6,2g,2c6,2g,2c6"
pager
curl "http://10.1.1.251/control?cmd=rtttl,5:d=4,o=5,b=160:8d6,16p,2d6,16p,8d6,16p,2d6,16p,8d6,16p,2d6"
Update 20221208 – removed internals
Removed my old hack and replaced it with a Wemos D1.
Added a LED
Next to do .. add a amplifier using a LM356/358
Music Page Turner
UPDATE: 20230320 new version
My first version of the Bluetooth page turner.
This was made using an Arduino and some buttons.
I’m using Fbreader and Ebookdroid on the tablet.
Code:
Note: Volume buttons work for both apps, if you want to use other keys, you need to put a keymap.xml file in your fbreader books directory on your android device to remap those!
#include <BleKeyboard.h> #define RIGHT_TURN 4 #define LEFT_TURN 5 BleKeyboard bleKeyboard("fashpageturner", "Bluetooth Device Manufacturer", 100); void setup() { bleKeyboard.begin(); pinMode(LEFT_TURN, INPUT_PULLUP); pinMode(RIGHT_TURN, INPUT_PULLUP); } void loop() { if (bleKeyboard.isConnected() && !digitalRead(RIGHT_TURN)) { bleKeyboard.press(KEY_MEDIA_VOLUME_UP); delay (100); bleKeyboard.releaseAll(); } if (bleKeyboard.isConnected() && !digitalRead(LEFT_TURN)) { bleKeyboard.press(KEY_MEDIA_VOLUME_DOWN); delay (100); bleKeyboard.releaseAll(); } }
NEW Version



CPU / Memory analog meters
Today i used some analog meters to display cpu load and memory usage.
Using below 12 bit DAC (MCP4725 ) and a Wemos Mini
Usage: (Anything you can come up with, if you got a value, you can display it)
curl http://IP/specificArgs?dac_value=$(grep 'cpu ' /proc/stat | awk '{usage=($2+$4)*1000} END {print usage }' |cut -f1 -d.)
Arduino code
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <Wire.h>
#include <Adafruit_MCP4725.h>
#define MCP4725 0x62
unsigned int adc;
byte buffer[3];
Adafruit_MCP4725 dac;
char dac_value_tmp[6] = "0";
int dac_value = 0;
ESP8266WebServer server(80); //Web server
void setup() {
Wire.begin();
Serial.begin(115200);
WiFi.begin("accesspoint", "accesspointpass");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.println("Waiting to connect…");
}
Serial.print("IP address: ");
Serial.println(WiFi.localIP()); //Print IP
server.on("/genericArgs", handleGenericArgs);
server.on("/specificArgs", handleSpecificArg);
server.begin(); //Start the server
Serial.println("Server listening");
dac.begin(0x60); // The I2C Address
}
void loop() {
uint32_t dac_value;
int adcValueRead = 0;
float voltageRead = 0;
server.handleClient();
}
void handleGenericArgs() { //Handler
String message = "Number of args received:";
message += server.args(); //Get number of parameters
message += "\n";
for (int i = 0; i < server.args(); i++) {
message += "Arg nº" + (String)i + " –> ";
message += server.argName(i) + ": ";
message += server.arg(i) + "\n";
}
server.send(200, "text/plain", message);
}
void handleSpecificArg() {
String message = "";
if (server.arg("dac_value")== ""){ //Parameter not found
message = "dac_value Argument not found";
}else{
message = "dac_value = ";
message += server.arg("dac_value"); //Gets the value of the query parameter
int dac_value = server.arg("dac_value").toInt();
Serial.print("DAC Value: ");
Serial.print(dac_value);
buffer[0] = 0b01000000;
buffer[1] = dac_value >> 4; //Puts the most significant bit values
buffer[2] = dac_value << 4; //Puts the Least significant bit values
Wire.beginTransmission(MCP4725); //Joins I2C bus with MCP4725 with 0x61 address
Wire.write(buffer[0]); //Sends control byte
Wire.write(buffer[1]); //Sends the MSB to I2C
Wire.write(buffer[2]); //Sends the LSB to I2C
Wire.endTransmission(); //Ends the transmission
}
server.send(200, "text/plain", message); //Returns the HTTP response
}


Resistor depends on the range of your analog meters
Macro Buttons
A box with macro buttons for your PC using Arduino Leonardo
#include <Keypad.h> // matrix read #include <Keyboard.h> // keyboard out #define ENABLE_PULLUPS // fuck the resistors #define NUMBUTTONS 25 // matrix #define NUMROWS 5 // matrix rows #define NUMCOLS 5 // matrix cols int analog1 = A3; int analog2 = A7; int inPinctrl = 3; // function ctrl, pull to vcc int inPinalt = 4; // function alt, pull to vcc int valctrl = 0; // variable to store shifter int valalt = 0; // variable to store shifter int joyx = 0; int joyy = 0; //define the symbols per key char buttons[NUMROWS][NUMCOLS] = { {'q','w','e','r','t'}, {'y','u','i','o','p'}, {'a','s','d','f','g'}, {'h','j','k','l','z'}, {'x','c','v','b','n'}, }; // q-1 (star) e-zoomin r-prev t-up // y-2 u-clearstar o-open p-down // a-3 (rate) d-zoomreset f-full g-left // h-4 j-clearrate l-esc z-right // x-5 c-slideshow v=zoomout b-next // 14 16 10 9 8 // 21 q y a h x // 20 w u s j c // 19 e i d k v // 18 t p g z n // 15 r o f l b byte rowPins[NUMROWS] = {16,20,19,18,15}; //connect to the row pinouts of the keypad byte colPins[NUMCOLS] = {14,7,10,9,8}; //connect to the column pinouts of the keypad //initialize an instance of class NewKeypad Keypad buttbx = Keypad( makeKeymap(buttons), rowPins, colPins, NUMROWS, NUMCOLS); void setup() { Serial.begin(115200); // debug out baud pinMode(inPinctrl, INPUT); // sets the digital pin 3 as input pinMode(inPinalt, INPUT); // sets the digital pin 4 as input digitalWrite(inPinctrl, HIGH); // turn on pullup resistors digitalWrite(inPinalt, HIGH); // turn on pullup resistors Keyboard.begin(); // keyb starter } void loop() { // loop the program CheckAllButtons(); // check tha buttons } void CheckAllButtons(void) { joyx = analogRead(analog1); joyy = analogRead(analog2); Serial.println(joyx); Serial.println(joyy); if (joyx > 900) { Keyboard.press(KEY_UP_ARROW); delay(150); Keyboard.releaseAll(); } if (joyx < 200) { Keyboard.press(KEY_DOWN_ARROW); delay(150); Keyboard.releaseAll(); } if (joyy > 900) { Keyboard.press(KEY_LEFT_ARROW); delay(150); Keyboard.releaseAll(); } if (joyy < 200) { Keyboard.press(KEY_RIGHT_ARROW); delay(150); Keyboard.releaseAll(); } char key = buttbx.getKey(); if (key != NO_KEY) { valctrl = digitalRead(inPinctrl); // read the function pin valalt = digitalRead(inPinalt); // read the function pin Serial.write(valctrl); // debug Serial.println(); // enter Serial.write(valalt); // debug Serial.println(); // enter Serial.write(key); // debug Serial.println(); // enter // button 1 if (key == 'q') { if (valctrl == 0) { // function shifter active? Keyboard.press(KEY_LEFT_CTRL); } if (valalt == 0) { // function shifter active? Keyboard.press(KEY_LEFT_ALT); } Keyboard.press('1'); delay(150); Keyboard.releaseAll(); } // button 2 if (key == 'y') { if (valctrl == 0) { // function shifter active? Keyboard.press(KEY_LEFT_CTRL); } if (valalt == 0) { // function shifter active? Keyboard.press(KEY_LEFT_ALT); } Keyboard.press('2'); delay(150); Keyboard.releaseAll(); } // button 3 if (key == 'a') { if (valctrl == 0) { // function shifter active? Keyboard.press(KEY_LEFT_CTRL); } if (valalt == 0) { // function shifter active? Keyboard.press(KEY_LEFT_ALT); } Keyboard.press('3'); delay(150); Keyboard.releaseAll(); } // button 4 if (key == 'h') { if (valctrl == 0) { // function shifter active? Keyboard.press(KEY_LEFT_CTRL); } if (valalt == 0) { // function shifter active? Keyboard.press(KEY_LEFT_ALT); } Keyboard.press('4'); delay(150); Keyboard.releaseAll(); } // button 5 if (key == 'x') { if (valctrl == 0) { // function shifter active? Keyboard.press(KEY_LEFT_CTRL); } if (valalt == 0) { // function shifter active? Keyboard.press(KEY_LEFT_ALT); } Keyboard.press('5'); delay(150); Keyboard.releaseAll(); } // button i - clear rate if (key == 'i') { Keyboard.press(KEY_LEFT_CTRL); Keyboard.press('0'); delay(150); Keyboard.releaseAll(); } // button k - clear label if (key == 'k') { Keyboard.press(KEY_LEFT_ALT); Keyboard.press('0'); delay(150); Keyboard.releaseAll(); } // button v - slideshow if (key == 'v') { Keyboard.press(KEY_ESC); Keyboard.press(KEY_LEFT_CTRL); Keyboard.press('s'); delay(150); Keyboard.releaseAll(); } // button t - zoomin if (key == 't') { Keyboard.press('+'); delay(150); Keyboard.releaseAll(); } // button g - zoomreset if (key == 'g') { Keyboard.press('*'); delay(150); Keyboard.releaseAll(); } // button n - zoomout if (key == 'n') { Keyboard.press('-'); delay(150); Keyboard.releaseAll(); } //r o f l b // button r - prev if (key == 'r') { Keyboard.press(KEY_LEFT_CTRL); Keyboard.press(KEY_LEFT_ARROW); delay(150); Keyboard.releaseAll(); } // button o - open if (key == 'o') { Keyboard.press(KEY_RETURN); delay(150); Keyboard.releaseAll(); } // button f - full if (key == 'f') { Keyboard.press('f'); delay(150); Keyboard.releaseAll(); } // button l - esc if (key == 'l') { Keyboard.press(KEY_ESC); delay(150); Keyboard.releaseAll(); } // button b - next if (key == 'b') { Keyboard.press(KEY_LEFT_CTRL); Keyboard.press(KEY_RIGHT_ARROW); delay(150); Keyboard.releaseAll(); } } }
Pressure Lab
For measuring pressure in fermentation containers, I designed a pressure sensor which could be wireless connected to a fermentation container.
The sensor would transmit the values to a Raspberry which was configured as a Access Point and would store the measurements and generated graphs using Grafana.













Nodes config:
Esp configuration, connect with micro-usb
Flashing with linux
esptool.py -p /dev/ttyUSB0 write_flash 0x00000 ESP_Easy_mega-20190311_normal_ESP8266_4M.bin
Make a connection with the ESP Access point
Connect esp with a power source.
Look for a AP with ESP_Easy_0
Use password “configesp” to connect
Start you browser and enter http://192.168.4.1

In wifi wizard setup select “pressurespot”
Enter password “pressurespot”
Press connect
Wait 20s and look in the raspberry logs which IP the ESP got.
Connect laptop/mobile to wifi “pressurespot”and connect
Enter found IP from ESP in your browser.
Proceed to main config
Main setting table, set the following
- Unit name & number + append
- SSID and WPA key pressurespot
- Client IP block level allow all
- Press submit
Press controller tab
Press first edit button and set following
– Protocol: domoticz http
Next set
– Controller IP : 10.42.0.1
– Toggle enabled and press submit
Resulting in:
Next we got to Hardware
I2C interface switch GPIO-4 and GPIO-5
- GPIO – SDA: GPIO-4 (D2) change to GPIO-5 (D1)
- GPIO – SCL: GPIO-5 (D1) change to GPIO-4 (D2)
- Press “Submit”
Devices TAB
Press edit, and select device “Environment – BMx280” from the pulldown menu.
Next, set the following
- Name: pressure
- Enable on
- I2C address : 0x76 ( Is there is no 0x76 of 0x77 .. do a i2c scan on the next tab )
- Send to controller , mark this
- IDX: give this the number you had given this node (this is the one you have to use in domoticz )
- interval 10Seconds
- and press submit
In the Devices tab, you should be able to see the sensor with the values (Temperature and pressure)
No values? Do a i2c scan and/or reboot ESP ( You can find these in the tools tab)
Tools TAB
Press I2C scan, when seeing a address like 0x76 or 0x77 use this in previous tabs.
Still nothing, even after reboot? Maybe faulty hardware?
Everything okay? Back to the config tab
We are going to set the sleep mode.
Warning ! .. when setting this it is hard to get into the config pages again.
ESP will startup, connect to wifi, send values and goes to sleep again.
At the bottom set: Sleep awake time 1 sec
Buttons on the raspberry / pressurespot
Red button :
- Less than 3 seconds is reboot
- Longer than 3 seconds is shut down
- Charger can be removed, when the green light is off
Led lights on the sensors
- Red light (R2; constant): battery is charging
- Blue light (R1; constant): battery is full
- Blue light (R1; constant) & red light (R2; blinking): trying to charge, but no battery connected
Add shutdown script to /etc/rc.local
python /usr/local/bin/power-switch.py &
/usr/local/bin/power-switch.py
#!/usr/bin/python import threading, subprocess import RPi.GPIO as GPIO def shutdown(): subprocess.call('sudo shutdown -h now', shell=True) def edge_detected(pin): if GPIO.input(pin): t.cancel() subprocess.call('sudo reboot', shell=True) else: t.start() if __name__ == '__main__': try: GPIO.setmode(GPIO.BOARD) GPIO.setup(5, GPIO.IN) GPIO.add_event_detect(5, GPIO.BOTH, callback=edge_detected, bouncetime=10) t = threading.Timer(3.0, shutdown) while True: pass finally: GPIO.cleanup()
/usr/local/bin/ledoff.py
#!/usr/bin/python import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) GPIO.setup(18,GPIO.OUT) GPIO.output(18,GPIO.LOW)
/usr/local/bin/ledon.py
#!/usr/bin/python import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) GPIO.setup(18,GPIO.OUT) GPIO.output(18,GPIO.HIGH)
nmcli device wifi hotspot ssid pressurespot password pressurespot
/etc/NetworkManager/system-connections/Hotspot-1
[connection]
id=Hotspot-1
uuid=c2c05528-63f9-44c7-93ce-264187a45086
type=wifi
permissions=
timestamp=1553708934
[wifi]
hidden=true
mac-address=B8:27:EB:7F:D5:E7
mac-address-blacklist=
mode=ap
seen-bssids=B8:27:EB:7F:D5:E7;
ssid=pressurespot
[wifi-security]
group=ccmp;
key-mgmt=wpa-psk
pairwise=ccmp;
proto=rsn;
psk=pressurespot
[ipv4]
dns-search=
method=shared
[ipv6]
addr-gen-mode=stable-privacy
dns-search=
method=ignore
/usr/bin/servicecheck.sh (in rc.local and crontab root user – every minute
#!/bin/bash nmcli connection show | grep "Hotspot-1 c2c05528-63f9-44c7-93ce-264187a45086 802-11-wireless wlan0" >/dev/null && touch /tmp/wlan || rm -f /tmp/wlan for f in influx domoticz telegraf grafana mosquitto ; do pgrep $f >/dev/null && touch /tmp/$f || rm -f /tmp/$f done count=$(ls /tmp/influx /tmp/domoticz /tmp/telegraf /tmp/grafana /tmp/mosquitto /tmp/wlan | wc -l) if [ $count -eq 6 ] ; then /usr/local/bin/ledon.py exit 0 fi for timer in {1..10} ; do /usr/local/bin/ledon.py sleep 1 /usr/local/bin/ledoff.py sleep 1 done
Rest services to be installed on Raspberry
At the moment the raspberry uses domoticz between the Mqtt broker (Mosquitto) and the database (Influx)
Data wil be displayed using grafana.
tail -f /var/log/syslog shows which ip to which ESP
DHCPACK(wlan0) 10.42.0.104 cc:50:e3:c4:96:61 lab-
DHCPACK(wlan0) 10.42.0.181 cc:50:e3:c4:8d:73 lab-4
DHCPACK(wlan0) 10.42.0.186 cc:50:e3:c4:9b:ef lab-1
Configuring the raspberry
Install influx and grafana
First we add Influx repositories to apt:
wget -qO- https://repos.influxdata.com/influxdb.key | sudo apt-key add - source /etc/os-release echo "deb https://repos.influxdata.com/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/influxdb.list
Update apt with the new repo & install.
sudo apt update && sudo apt install -y influxdb
Then start the influxdb
service and set it to run at boot:
sudo systemctl enable influxdb --now
Again we need to add the Grafana packages to apt:
wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add - echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee /etc/apt/sources.list.d/grafana.list
We can now update and install the binaries:
sudo apt update && sudo apt install -y grafana
Then simply enable the service and set to run at boot:
sudo systemctl enable grafana-server.service --now
Now we can check that grafana is up by loading it in a browser: http://10.42.0.1:3000
. If so, you can log in with the username and password = admin
and set a new admin password.
Install mosquitto
sudo apt install mosquitto mosquitto-clients
Install domoticz using below command
<code><strong>curl -sSL install.domoticz.com | sudo bash</strong></code>
Under hardware add MQTT server adress 127.0.0.1
Add virtual sensors to domoticz.
Click hardware and create virtual sensor, lab with sensornumber. Sensor type is Temp+Baro.
When looking at devices you will see the virtual devices.
Pushing the data into Influxdb:
Goto settings > more options > data push > influxdb
Add temperature
- Device name: lab* (lab plus unit number)
- Value to send: temperature
- Target type: direct (NOTE screenshot below is wrong)
- press add
Add barometer
- Device name: lab* (lab plus unit number)
- Value to send: Barometer
- Target type: direct (NOTE screenshot below is wrong)
- press add
Configure Grafana
Go with your browser to http://10.42.0.1 when connected to the rpi access point
Goto settings and data sources, add influxdb with source http://localhost:8086
Goto dashboard and create a new one.

TODO
Telegraf/mosquito
Services in domoticz
Rpi status display
Sensor test / monitor