I used OpenCV to track my face, and draw something that moves with me when i move.
Just a prove of concept. I will post used code when i find it back.
All posts by fash
Bluetooth Macro Keyboard for Photo Management
- Cursor pad on the left
- 1 till 5 (see below)
- star + 1-5, rates 1 till 5 stars
- outline star – removes rating
- bookmark + 1-5, color marks image
- Triangle – start slideshow
- zoom-in, rotate CCW, reset zoom, rotate CW, zoom-out
- previous image, open image, fullscreen, exit fullscreen to manager and next image
I’ve used a esp32 with 18650 battery holder.
I still have to 3d print a case ๐
Code:
#include <BleConnectionStatus.h>
#include <BleKeyboard.h>
#include <KeyboardOutputCallbacks.h>
#define DEBUG 0micro joystick
#define STAR 16
#define FLAG 17
#define COL1 18
#define COL2 19
#define COL3 21
#define COL4 22
#define COL5 23
#define COL6 25
#define ROW1 26
#define ROW2 27
#define ROW3 32
#define ROW4 33
int flagstate = 0;
int starstate = 0;
int row1state = 0;
int row2state = 0;
int row3state = 0;
int row4state = 0;
int col1state = 0;
int col2state = 0;
int col3state = 0;
int col4state = 0;
int col5state = 0;
int col6state = 0;
int colstate = 1;
BleKeyboard bleKeyboard;
void setup() {
#ifdef DEBUG
Serial.begin(9600);
#endif
bleKeyboard.begin();
pinMode(STAR, INPUT_PULLUP);
pinMode(FLAG, INPUT_PULLUP);
pinMode(ROW1, INPUT_PULLUP);
pinMode(ROW2, INPUT_PULLUP);
pinMode(ROW3, INPUT_PULLUP);
pinMode(ROW4, INPUT_PULLUP);
pinMode(COL1, OUTPUT);
pinMode(COL2, OUTPUT);
pinMode(COL3, OUTPUT);
pinMode(COL4, OUTPUT);
pinMode(COL5, OUTPUT);
pinMode(COL6, OUTPUT);
}
void loop() {
#ifdef DEBUG
Serial.print("Colstate : ");
Serial.print(colstate);
Serial.print('\n');
#endif
if (colstate == 1) {
digitalWrite(COL1, LOW);
digitalWrite(COL2, HIGH);
digitalWrite(COL3, HIGH);
digitalWrite(COL4, HIGH);
digitalWrite(COL5, HIGH);
digitalWrite(COL6, HIGH);
}
if (colstate == 2) {
digitalWrite(COL1, HIGH);
digitalWrite(COL2, LOW);
digitalWrite(COL3, HIGH);
digitalWrite(COL4, HIGH);
digitalWrite(COL5, HIGH);
digitalWrite(COL6, HIGH);
}
if (colstate == 3) {
digitalWrite(COL1, HIGH);
digitalWrite(COL2, HIGH);
digitalWrite(COL3, LOW);
digitalWrite(COL4, HIGH);
digitalWrite(COL5, HIGH);
digitalWrite(COL6, HIGH);
}
if (colstate == 4) {
digitalWrite(COL1, HIGH);
digitalWrite(COL2, HIGH);
digitalWrite(COL3, HIGH);
digitalWrite(COL4, LOW);
digitalWrite(COL5, HIGH);
digitalWrite(COL6, HIGH);
}
if (colstate == 5) {
digitalWrite(COL1, HIGH);
digitalWrite(COL2, HIGH);
digitalWrite(COL3, HIGH);
digitalWrite(COL4, HIGH);
digitalWrite(COL5, LOW);
digitalWrite(COL6, HIGH);
}
if (colstate == 6) {
digitalWrite(COL1, HIGH);
digitalWrite(COL2, HIGH);
digitalWrite(COL3, HIGH);
digitalWrite(COL4, HIGH);
digitalWrite(COL5, HIGH);
digitalWrite(COL6, LOW);
}
delay (100);
flagstate = digitalRead(FLAG);
starstate = digitalRead(STAR);
row1state = digitalRead(ROW1);
row2state = digitalRead(ROW2);
row3state = digitalRead(ROW3);
row4state = digitalRead(ROW4);
#ifdef DEBUG
Serial.print("Rowstates : ");
Serial.print(row1state);
Serial.print(row2state);
Serial.print(row3state);
Serial.print(row4state);
Serial.print('\n');
#endif
// ROW1 = UP,DOWN,LEFT,RIGHT
if (bleKeyboard.isConnected() && colstate == 1) {
// UP
#ifdef DEBUG
Serial.print("Up Pressed ");
Serial.print('\n');
#endif
if (row1state == 0) {
bleKeyboard.press(KEY_UP_ARROW);
delay (100);
bleKeyboard.releaseAll();
}
// DOWN
if (row2state == 0) {
bleKeyboard.press(KEY_DOWN_ARROW);
delay (100);
bleKeyboard.releaseAll();
}
// LEFT
if (row3state == 0) {
bleKeyboard.press(KEY_LEFT_ARROW);
delay (100);
bleKeyboard.releaseAll();
}
// RIGHT
if (row4state == 0) {
bleKeyboard.press(KEY_RIGHT_ARROW);
delay (100);
bleKeyboard.releaseAll();
}
}
// ROW2 = (1),(star),ZOOMIN,PREVIOUS
if (bleKeyboard.isConnected() && colstate == 2) {
// 1 - star
if (row1state == 0 && starstate == 0) {
bleKeyboard.press(KEY_LEFT_CTRL);
bleKeyboard.press('1');
delay (100);
bleKeyboard.releaseAll();
}
// 1 - flag
if (row1state == 0 && flagstate == 0) {
bleKeyboard.press(KEY_LEFT_ALT);
bleKeyboard.press('1');
delay (100);
bleKeyboard.releaseAll();
}
// NO ROWSTATE2
// zoom in
if (row3state == 0) {
bleKeyboard.press('+');
delay (100);
bleKeyboard.releaseAll();
}
// PREVIOUS
if (row4state == 0) {
bleKeyboard.press(KEY_LEFT_CTRL);
bleKeyboard.press(KEY_LEFT_ARROW);
delay (100);
bleKeyboard.releaseAll();
}
}
// ROW3 = (2),unstar,CCWrotate,open
if (bleKeyboard.isConnected() && colstate == 3) {
// 2 - star
if (row1state == 0 && starstate == 0) {
bleKeyboard.press(KEY_LEFT_CTRL);
bleKeyboard.press('2');
delay (100);
bleKeyboard.releaseAll();
}
// 2 - flag
if (row1state == 0 && flagstate == 0) {
bleKeyboard.press(KEY_LEFT_ALT);
bleKeyboard.press('2');
delay (100);
bleKeyboard.releaseAll();
}
// unstar
if (row2state == 0) {
bleKeyboard.press(KEY_LEFT_CTRL);
bleKeyboard.press('0');
delay (100);
bleKeyboard.releaseAll();
}
// CCW rotate
if (row3state == 0) {
bleKeyboard.press(KEY_LEFT_CTRL);
bleKeyboard.press(KEY_LEFT_ALT);
bleKeyboard.press(KEY_LEFT_ARROW);
delay (100);
bleKeyboard.releaseAll();
}
// open
if (row4state == 0) {
bleKeyboard.press(KEY_RETURN);
delay (100);
bleKeyboard.releaseAll();
}
}
// ROW4 = (3),(flag),zoom,fullscreen
if (bleKeyboard.isConnected() && colstate == 4) {
// 3 - star
if (row1state == 0 && starstate == 0) {
bleKeyboard.press(KEY_LEFT_CTRL);
bleKeyboard.press('3');
delay (100);
bleKeyboard.releaseAll();
}
// 3 - flag
if (row1state == 0 && flagstate == 0) {
bleKeyboard.press(KEY_LEFT_ALT);
bleKeyboard.press('3');
delay (100);
bleKeyboard.releaseAll();
}
// NO ROWSTATE2
// zoom reset
if (row3state == 0) {
bleKeyboard.press('*');
delay (100);
bleKeyboard.releaseAll();
}
// fullscreen
if (row4state == 0) {
bleKeyboard.press('f');
delay (100);
bleKeyboard.releaseAll();
}
}
// ROW5 = (4),unflag,CWrotate,exit
if (bleKeyboard.isConnected() && colstate == 5) {
// 4 - star
if (row1state == 0 && starstate == 0) {
bleKeyboard.press(KEY_LEFT_CTRL);
bleKeyboard.press('4');
delay (100);
bleKeyboard.releaseAll();
}
// 4 - flag
if (row1state == 0 && flagstate == 0) {
bleKeyboard.press(KEY_LEFT_ALT);
bleKeyboard.press('4');
delay (100);
bleKeyboard.releaseAll();
}
// unflag
if (row2state == 0) {
bleKeyboard.press(KEY_LEFT_ALT);
bleKeyboard.press('0');
delay (100);
bleKeyboard.releaseAll();
}
// CW rotate
if (row3state == 0) {
bleKeyboard.press(KEY_LEFT_CTRL);
bleKeyboard.press(KEY_LEFT_ALT);
bleKeyboard.press(KEY_RIGHT_ARROW);
delay (100);
bleKeyboard.releaseAll();
}
// exit
if (row4state == 0) {
bleKeyboard.press(KEY_ESC);
delay (100);
bleKeyboard.releaseAll();
}
}
// ROW6 = (5),slideshow,zoomout,next
if (bleKeyboard.isConnected() && colstate == 6) {
// 5 - star
if (row1state == 0 && starstate == 0) {
bleKeyboard.press(KEY_LEFT_CTRL);
bleKeyboard.press('5');
delay (100);
bleKeyboard.releaseAll();
}
// 5 - flag
if (row1state == 0 && flagstate == 0) {
bleKeyboard.press(KEY_LEFT_ALT);
bleKeyboard.press('5');
delay (100);
bleKeyboard.releaseAll();
}
// slideshow
if (row2state == 0) {
bleKeyboard.press(KEY_ESC);
bleKeyboard.press(KEY_LEFT_CTRL);
bleKeyboard.press('s');
delay (100);
bleKeyboard.releaseAll();
}
// zoom out
if (row3state == 0) {
bleKeyboard.press('-');
delay (100);
bleKeyboard.releaseAll();
}
// next
if (row4state == 0) {
bleKeyboard.press(KEY_LEFT_CTRL);
bleKeyboard.press(KEY_RIGHT_ARROW);
delay (100);
bleKeyboard.releaseAll();
}
}
colstate++;
if (colstate == 7) {
colstate = 1;
}
}
Laser engraving

Bought a laser engraving kit, which can be mounted on my 3D Creality Printer, using magnets.
I’ve connected the power to a fan connector in 3D printer. So it can be controlled with gcode’s
M18 Z; stop Z axes, use only X and YM106 ; laser on commandM107 ; laser stop command
I’ve created a bash script which outlines our design with minimal and maximal x and y coordinates, so you can allign your object just in the right place.
It uses a low voltage on you laser, so its visible but it doesn’t burn you object.
#!/bin/bash
myz=100
MAXX=$(cat "$1" | grep "G0 X" | awk '{ print $2 }' | cut -c2- | sort -n | tail -1)
MINX=$(cat "$1" | grep "G0 X" | awk '{ print $2 }' | cut -c2- | sort -n | head -1)
MAXY=$(cat "$1" | grep "G0 X" | awk '{ print $3 }' | cut -c2- | sort -n | tail -1)
MINY=$(cat "$1" | grep "G0 X" | awk '{ print $3 }' | cut -c2- | sort -n | head -1)
cat > "pointtest - $1" << EOF
;BingoStart
G90
M17 Z
G0 F3000
G0 $myz F3000
M18 Z
G0 X${MINX} Y${MINY}
M106 S2
G0 F3000
G0 X${MINX} Y${MAXY}
M106 S2
G0 F3000
G0 X${MAXX} Y${MAXY}
M106 S2
G0 F3000
G0 X${MAXX} Y${MINY}
M106 S2
G0 F3000
G0 X${MINX} Y${MINY}
M106 S2
G0 F3000
G0 X${MINX} Y${MAXY}
M106 S2
G0 F3000
G0 X${MAXX} Y${MAXY}
M106 S2
G0 F3000
G0 X${MAXX} Y${MINY}
M106 S2
G0 F3000
G0 X${MINX} Y${MINY}
M106 S2
M107
;end
EOF
Below a offset fixer
#!/bin/bash
myz=100
cat "$1" | sed s/Z1/Z${myz}/g | sed s/Z6/Z${myz}/g > "fixed.$1"

Repairing my Concertina
UPDATE: 7 Jan 2023 – Another repair
15 Feb of this year my Concertina was deliverd on my doorstep.
It is a Wren 2 Anglo C/G Concertina by McNeela. A affordable good instrument.
Features
- 30 button Anglo Concertina in the key of C/G
- Fully chromatic
- Measures 6.3″ across the flats (16cm)
- 8 fold bellows
- Steel reeds
- Loud, crisp tone
- Durable black buttons
- Wheatstone/Lachenal layout
- Excellent response
- Easy to play
- Lightweight concertina – easy to handle for all ages
- Traditional size – unlike other bulky beginner concertinas
- Softer, more comfortable, adjustable hand-straps – suitable for both children and adults
- Finished with improved stylish gloss exposed-grain wood
- Comes with a complimentary Concertina Padded Hard Case
The word concertina refers to a family of hand-held bellows-driven free reed instruments constructed according to various systems, which differ in terms of keyboard layout, and whether individual buttons (keys) produce the same (unisonoric) or different (bisonoric) notes with changes in the direction of air pressure.
It is weird playing two notes with the same button, but i gives you a broader tonal range. Some notes are double, one on the pull action and one on the push action. When playing for a while it is possible to switch between those two to be able to play faster.
Because you can use the same pull or push as you already where playing, or the button is close by the one you already play.

So i had a little problem with the pull motion of the right hand A’ B’.
I didn’t want to send my Concertina back (Still has garantee, i know)
But sending it back to Ireland will take a while and has postal costs.
(I’ve fixed my Accordeon also, so why not try to fix it myself?)
(… aaand i was curious of the insides )



I had to look at the inner workings for a minute, and finding the right reed.
The middle picture above shows a white plastic strip, one of them was stuck. Moving it a little and carefully bending it, got it free and moveable again.
On with the lessons from Caitlin Nic Gabhann again!
https://www.youtube.com/watch?v=Z3tPzc6kKM0
2023 Repair:
One of the reeds fell off! It was not glued properly. A 5 minute fix!
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
}
]
Mattermost Mqtt Flag Integration
UPDATE 20231020 – Via USB Serial (also schematic for below integration)
https://www.henriaanstoot.nl/2023/10/20/thunderbird-mail-notification-flag-via-usb/
Using a servo which is MQTT controlled, and a slash command in Mattermost, i can be notified by friends and colleages.
Flag, and monitor-stand are 3D printed.
ESP is a simple wemos mini.
Laser pointer web controlled
Coline sometimes plays games with her sisters online using my streaming server. (Due to Covid)
Some games are difficult because you have to point to a location on the table. So i came up with a laser pointer solution.



The idea is: Send a url to the players with a streaming camera, you see the game on your screen but you can click on a location on the screen to move a laser pointer to that location.
Below is a proof of concept using the Lasercut worldmap on the wall and a website with a worldmap.


Code to place on the ESP:
This will connect to the MQTT broker and listens for messages on the servo/pan and tilt topic.
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Servo.h>
Servo pan;
Servo tilt;
const char* ssid = "MYSSI";
const char* password = "MYWIFIPASS";
const char* mqtt_server = "IPMQTTBROKER";
const char* topic_pan = "servo/pan";
const char* topic_tilt = "servo/tilt";
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;
void setup() {
pan.attach(D5);
tilt.attach(D6);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}
void setup_wifi() {
delay(5);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
}
void callback(char* topic, byte* payload, unsigned int length) {
String string;
for (int i = 0; i < length; i++) {
string+=((char)payload[i]);
}
int pos = string.toInt();
if ( strcmp(topic, topic_pan) == 0 ) {
pan.write(pos);
}
if ( strcmp(topic, topic_tilt) == 0 ) {
tilt.write(pos);
}
delay(15);
}
void reconnect() {
while (!client.connected()) {
if (client.connect("ESP8266Client")) {
client.subscribe(topic_pan);
client.subscribe(topic_tilt);
} else {
delay(5000);
}
}
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
delay(100);
}
Website PHP code:
This has some calibration code to get coordinates lined-up
<?Php
$foo_x=$_POST['foo_x'];
$foo_y=$_POST['foo_y'];
echo "X=$foo_x, Y=$foo_y ";
$x=160 - round($foo_x/30);
$y=38 - round($foo_y/100);
system('/usr/bin/mosquitto_pub -h 10.1.0.17 -t servo/pan -m "' . $x . '"');
system('/usr/bin/mosquitto_pub -h 10.1.0.17 -t servo/tilt -m "' . $y . '"');
?>
<form action='' method=post>
<input type="image" alt=' Finding coordinates of an image' src="worldmap.jpg"
name="foo" style=cursor:crosshair;/>
</form>
POC
Laser engraved my laptop



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.


Movie genre’s
We are movieholic’s. Watching everything. Sometimes we thing “why the F did we watch that” other times it’s a pretty unknown jewel.
We loved “De kijk van Koolhoven” a dutch tv serie about movies, by our dutch director Martin van Koolhoven.
He explained why he liked certain movies. Tarantino did simular but couldn’t find much about that
We started watching the top 250 IMDB movies a few years ago. Comming a long way, and has been a treat.
Below a list of top movies i could thing of in serveral genre’s.
Nowhere complete, and probably forgot better ones
Action
- 3 days of the condor
- Snowpiercer
- Maze runner
- Inferno
- Bourne series
- Enter the Dragon
- Fugitive
- John Wick
Animation
- Akira
- Ghost in the shell
- 9
- 5cm per second
- Tintin (2011)
- Beowulf
- Coco
- Song of the sea
Comedy
- guest house paradiso
- Life of brian
- “100-year old man who climbed out of the window”
- Blues brothers
- “Dont look now we’re being shot at”
- Groundhog day
- The man who sues god
- Mash attacks
- Modern times
- Great Dictator
- Airplane
Crime
- 12 Angry men
- The sting
- The Mule
- Oceans series
- “No Country for Old Men”
Drama
- Roma
- A beautiful mind
- Bicycle thieves
- Cast away
- Cinema Paradiso
- Green book
- Kite runner
- Man on the moon
- Seven samurai
- American Sniper
- Wadjda
Dutch
- Amsterdamed
- De Lift
- The Johnsons
- “Schippers van de Kameleon”
- Michiel de Ruijter
Fantasy
- The BFG
- Hobbit
- Lotr
- Labyrinth
- “The Imaginarium of Doctor Parnassus”
- Time bandits
- City of lost children
Film Noir
- Double indemnity
- Touch of evil
- Sin City
- M
Horror
- Alien
- Saw
- The Platform
- Underwater
- Them
- The Thing
- Troll hunter?
- Braindead
IT-Related
- Antitrust
- Hackers
- Tron
- Matrix
- Source code
- Swordfish
- Takedown
- War games
Mindfuck
- Looper
- Memento
- Oldboy
- Vertigo
- The Prestige
- Primer
- Time lapse
Pre-1940
- The general
- Metropolis
- Modern times
- Gold Rush
- M
SciFy
- Bladerunner
- Metropolis (silent)
- Attraction
- Inception
- Interstellar
- Martian
- Terminator
- Avatar
- Arrival (2016)
- Incredible shrinking man
- Them (1954)
Fun to watch
- 4Latas
War
- Live is beautiful
- Great escape
- Dunkirk
- The pianist
- T-34
- Oorlogswinter
- Schindler’s list
- Das boot
- Downfall
- Inglourious basterds
- The imitation game
- Ballad of a Soldier (1959)
- Escape from Sobibor (1987)
- painted bird (2019)
Weird
- Funky Forrest
- Existence
- Delicatessen
- Meet the feebles
- “Requiem for a dream”
- Swiss army man
- Tenet
- A clockwork orange
- “Curious case of Benjamin Button”
- The Lobster
- Zardoz
Western
- Revenant
- Brimstone
- Hang m high
- Good bad and the Ugly
- Magnificent Seven (1960)
Woman Power
- Jackie Brown
- Hidden figures
- Color Purple
- Moana / Brave
- Roma
- Alien
- The Piano
- Girl with the Dragon Tattoo
- A League of Their Own
- 9 to 5
- Kill bill
List for Maryse
- Zwartboek
- Red sea ding resort
- The pianist
- Schindler’s list
- Zwartboek
- Son of Saul
- Boy in the striped pyjama’s
- Waltz With Bashir
- La vita รจ bella
Indian movies
- Taare Zameen Par (2007) – Like stars on earth (is a tearjerker)
- 3 Idiots (2009)
- Slumdog millionaire (Techinally a british movie)
- Dangal (2016)










