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.

3D printed case

Schematics (without the wireless charging part)

Wireless 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.

Note the slash command, M5 stick flow is unrelated!

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.

Laser pointer module

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

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)

Where have we been map

Generated a world map where we’ve been … biggest red part .. seen the least of it ๐Ÿ™‚
Vacation or work
A small part of the US, and a small corner from the westcoast of Canada.

Countries/places on our todo list:

  • Mongolia
  • Japan
  • Cuba
  • Greece
  • America : Coline
  • Austria : Coline, Monique
  • Belgium : Monique, Coline
  • Bolivia : Coline, Arja
  • Cambodia : Coline, Monique
  • Canada : Monique, Coline
  • Canary islands : Coline
  • Czechia : Coline, Monique
  • Denmark : Coline
  • Egypt : Monique, Coline
  • England : Monique, Coline
  • France : Monique, Coline
  • Germany : Monique, Coline
  • Hungary : Monique, Coline
  • Iceland : Arja, Coline, Monique
  • Ireland : Coline, Monique
  • Italy : Monique, Coline
  • Laos : Monique, Coline
  • Malta : Coline
  • New Zealand: Coline
  • Peru : Arja, Coline
  • Romenia : Monique, Coline
  • Scotland : Monique, Coline (Many many times)
  • Spain : Coline
  • Sweden : Coline
  • Switzerland : Coline, Monique
  • Vietnam : Coline, Monique

Kodi movies and metadata

UPDATE: 20220307

I’m using Kodi for a long time now, but never was really satisfied with the results of automatically scraping metadata.

Movie names had to be just right, and changing some metadata was hard.

A while ago i made a NFO generator for own movies, digitized 8mm material, mobile movies etc.

So for movies/tv shows i started using Tinymediamanager for metadata management. You have more controll over your NFO files.
Don’t forget to add media sources to Kodi, selecting the ‘local NFO scraper’ option.

I’m using TVDB scraper in TMM, and trakt to mark seen.
But that way i’m missing IMDB top 250.

Fix:

  • Scrape metadata for selected movies
  • Choose IMDB as the Metadata scraper
  • Remember to DESELECT ALL metadata options with the exceptions of Rating , to keep your existing metadata.
TinyMediaManager Scraper page

UPDATE:
Problems with premiered date/release date showing up as movie date in kodi? Here is my fix.

find . -type f -name '*.nfo' -print -exec sed -i -e '/<premiered>/d' {} \;

Folk band instruments 2021

Today newest addition Concertina

Bert Visscher and Herman Finkers

Hacking a hikvision doorcam

I don’t like cloud enabled devices, except if it is my own cloud!

I bought a Hikvision doorcam, when i researched the diverse doorcams where was a hikvision which could use a existing doorchime.

When i got mine in, it did not have this feature.
Damn what to do!

Where where several solutions i could think off:

  • Use as is .. a no-go for me
  • Offload SSL on a proxy and try to reverse engineer the https communication
  • Or a hardware solution

I looked at the electronics and tried to find out how things where connected and where things where you could make use of.
I soldered some wires to a little print where the pushbutton was located.
Now i could read the button press, video was easily captured by using a RTSP port.

Does it work? … yes, but i’m not happy about it

Video playback in Zoneminder or VLC

rtsp://admin:secretpassword@hikvisionip:554/Streaming/Channels/101

A solution i used before for a generic doorbell

Just read the gpio pin with Arduino or raspberry.
A generic optocoupler will work, just check your resistor.

"If something is worth doing, it's worth overdoing."