Category Archives: IOT / Domoticz

Mqtt blinker for topic notifications

Last year I’ve made a led pole with digital fireworks.

Time to replace for something else ..

I’ve made a mqtt 1-D game in december.

I needed to change a lot to the javascript on the website to fix some stuff.

  • Fix IPhone control. (I hate iphone)
  • Fix screenlock timeout
  • Added meta refresh

The XMAS/Fireworks controller was often used, and I got notifications via my TV. (see other posts)

Now I want to see when MQTT movement when I’m in the livingroom.
So I programmed a Wemos controller to blink the internal when MQTT messages are received.

CODE:

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

const char* ssid = "WIFIAP";
const char* password = "WIFIPASS";

const char* mqtt_server = "MQTTBROKER";  // MQTT broker IP
const char* mqtt_topic  = "game/tilt";

WiFiClient espClient;
PubSubClient client(espClient);

String lastPayload = "";

void setup_wifi() {
  delay(10);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
}

void blinkLED() {
    digitalWrite(LED_BUILTIN, LOW);   // LED ON
    delay(200);
    digitalWrite(LED_BUILTIN, HIGH);  // LED OFF
    delay(200);
}

void callback(char* topic, byte* payload, unsigned int length) {
  String message;
  for (unsigned int i = 0; i < length; i++) {
    message += (char)payload[i];
  }

  // Blink only if topic value changed
  if (message != lastPayload) {
    blinkLED();
    lastPayload = message;
  }
}

void reconnect() {
  while (!client.connected()) {
    if (client.connect("WemosClientMqttBlink")) {
      client.subscribe(mqtt_topic);
    } else {
      delay(2000);
    }
  }
}

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH); 

  setup_wifi();

  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
}

LoRa and more LoRa

I’ve been playing with LoRa for some time now, mostly with two adhoc LilyGO nodes.
After seeing a YT clip from Andreas Spiess I installed a meshtastic node on a Heltec V3.
Wanting more, I bought a Heltec V4 and an 8DBi (60cm) antenna.
Heltec V3 got a new home in Tyrone’s home.

GPS for the Heltec V4 module!

Via meshtastic I communicated with a guy here in the neighbourhood.
I installed Meshcore and my LoRa playground grew!

A Nebra Helium Miner was bought, and repurposed !

There is a Raspberry CM3 in there (Compute module)
Some big antenna’s and a waterproof case.
Using POE to power the thing, the plan is to have this installation at a high point around my house. (LED pole?!? 🙂 )

Meanwhile I got these : Seeed Xiao Lora ESP32 modules

MeshTUI

STM32 Nucleo-64 development board

I’ve been playing with all kinds of MicroControllers, but not this one.

Something new to learn.

The STM32 Nucleo-64 board provides a flexible way to try out the STM32 microcontroller. The Arduino Uno V3 can be connected as a shield.

STM32 excels in high-performance, deterministic industrial control with better real-time capability, lower power, and rich peripherals, using ARM Cortex-M cores, while ESP32 dominates IoT with built-in Wi-Fi/Bluetooth, lower cost, easier Arduino/PlatformIO access, and strong community, but with higher power and less precise real-time control (Xtensa cores), making ESP32 great for connected projects and STM32 for industrial/precision tasks.

STM32 (STMicroelectronics)
Strengths:

  • Performance: Superior real-time processing, deterministic behavior, efficient for complex control.
  • Power: Advanced low-power modes, excellent for battery-powered devices.
  • Peripherals: Rich, precise analog (ADC/DAC), extensive interface options (USB, SD, LCD).
  • Reliability: Strong for industrial, medical, and automotive applications.
  • Tools: STM32CubeIDE/MX, HAL/LL libraries.

    Weaknesses:
  • Higher cost and learning curve.
  • Requires external modules for Wi-Fi/Bluetooth.

ESP32 (Espressif Systems)
Strengths:

  • Connectivity: Integrated Wi-Fi and Bluetooth (BLE).
  • Cost & Ease: Cost-effective, easy entry with Arduino IDE/PlatformIO, great for rapid prototyping.
  • Community: Strong open-source community.
  • Features: Dual-core (often), built-in OTA updates, good for audio/AI.

    Weaknesses:
  • Less deterministic/real-time performance than STM32.
  • Higher active power consumption, less precise analog.
  • Can have complex debugging/compilation.
  • When to Choose Which
  • Choose STM32 for: Industrial automation, precise instrumentation, medical devices, complex motor control, low-power wearables, general embedded systems learning.
  • Choose ESP32 for: IoT devices, smart home products, Bluetooth beacons, educational projects, rapid prototyping, audio/voice applications.

Fireworks LED addition and modifying Arcade buttons

I’ve given people on the street control over my Xmas/Fireworks lights last month. (This month it is going to be converted to an interactive game)

I saw some LED strip dividers on Aliexpress, next year it’s going to have a star on top.

Like this….

Another LED related project I started today is a Whack-A-Mole game with multiple levels.
For this I need to convert a simple arcade button to a programmable multicolor version.

From single white LED to multi color, programmable.

Giving people ability to control my Xmas lights

At the WHY2025 hackers event, we used bigred’s antenna pole to make a huge sign using leds.

It gave me the idea to make a pole which displays digital “fireworks” using leds.
Fireworks are becoming illegal the next year in the Netherlands, I think.

So why not going digital?
12 Meter pole, 300 Leds.

There is a QR code and a website link mentioned on a page at the gate.
10 presets to select via a website.

Notification on my TV

While waiting for the first visitor I made a magnetic game.
Using a bunch of magnets, and 3D printed hexagon rings.
Two players try to place magnets in a small area without moving the others. If magnets slam together, you have more pieces to place.
(Below, last player has to take those 6 pieces)

CODE for website index.html

<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>WLED Mast</title>

<style>
body {
    background: #111;
    color: #fff;
    font-family: Arial;
    margin: 0;
    padding: 20px;
    text-align: center;
}
.grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 18px;
}
button {
    padding: 25px;
    font-size: 22px;
    border-radius: 20px;
    border: none;
    background: #333;
    color: #fff;
    font-weight: bold;
}
button:active {
    background: #555;
}
</style>
</head>

<body>

<h1>WLED Mast</h1>

<div class="grid">
    <button onclick="run('b1')">off</button>
    <button onclick="run('b2')">fireworks</button>
    <button onclick="run('b3')">sound<BR>reactive</button>
    <button onclick="run('b4')">bounch-balls</button>
    <button onclick="run('b5')">fire</button>
    <button onclick="run('b6')">juggle</button>
    <button onclick="run('b7')">swing</button>
    <button onclick="run('b8')">sparkle</button>
    <button onclick="run('b9')">popcorn</button>
    <button onclick="run('b10')">comet</button>
</div>

<script>
const API_KEY = "misuse-prevent";

function run(action) {
    fetch(`/action.php?action=${action}&key=${API_KEY}`)
        .then(r => r.json())
        .then(j => console.log(j))
        .catch(err => alert("Error"));
}
</script>

</body>
</html>

CODE for Wled API

<?php

$public_api_key = "misuse-prevent";
if (!isset($_GET['key']) || $_GET['key'] !== $public_api_key) {
    http_response_code(401);
    die("Unauthorized");
}

$action = $_GET['action'] ?? null;

// Map 10 buttons → WLED preset numbers
$allowed_actions = [
    "b1"  => 19,
    "b2"  => 22,
    "b3"  => 23,
    "b4"  => 20,
    "b5"  => 21,
    "b6"  => 3,
    "b7"  => 8,
    "b8"  => 2,
    "b9"  => 4,
    "b10" => 14
];

if (!$action || !isset($allowed_actions[$action])) {
    http_response_code(400);
    die("Invalid action");
}

$preset = $allowed_actions[$action];

// ---- WLED IP address ----
$wled_ip = "http://WLEDDEVICEIP";   // <-- CHANGE THIS

// API endpoint
$url = $wled_ip . "/win&PL=" . $preset;

// Call WLED directly
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($ch, CURLOPT_TIMEOUT, 2);

$response = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);

header("Content-Type: application/json");

if ($error) {
    echo json_encode(["ok" => false, "error" => $error]);
} else {
    echo json_encode(["ok" => true, "preset" => $preset]);
}

Working on the garden lights POC

Working on my garden lights

Working 12V relay bottom left, and upper right the Raspberry $ compute module board with NodeRed.

I made a little board to program the ATTiny85.

The RS485 chip I wanted to use (SN65HVD3082) came as SMD, luckily I have some SMD to THT/DIL boards. (breakoff)

Above on the breadboard : The SN65HVD3082EP on a little pcb, the ATTiny85 .
4×4 WS2812 led matrix will be my dimmable RGB garden light.

New MMWave boards.

Several years ago, I used some radar boards to detect movement.

After that I used a MMWave board

These are amazing, I’m using this in my Lab to switch on my big LED panel. You don’t need to move, it will detect human presence.
Another one I’m using in my living room.
It can power off all media at night (like TV, amplifier and lights)
It’s part of my home alarm system when we are away.

Now I got a new MMWave sensor (hlk-ld2450) , it can detect up to 3 persons and their location.


Screenshot from a Bluetooth phone app reading the sensor.

New afvalwijzer using Home Assistant

New version of :

New schematic using ESPHOME and has reset button (pressing the lid).
(Resets the LED when you’ve put the trash at the street curb.)

Above, a simplified version. I’m using 4 ws2812 leds now.

ESPHOME code:

esphome:
  name: afvalwemos
  friendly_name: AfvalWemos
  on_boot:
    priority: 800
    then:
    - delay: 1s
    - light.turn_off: main_leds

esp8266:
  board: d1_mini

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "bT76oR8vOxxxxxxxxxxxxxxxxxxxxxxxxQbyjY6M="

ota:
  - platform: esphome
    password: "c1dbxxxxxxxxxxxxxxxxxxxxxxxxxx36e75"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Afvalwemos Fallback Hotspot"
    password: "vVxxxxxxxxxxxxxxaw"

captive_portal:

# LED strip definition
light:
  - platform: neopixelbus
    type: RGB
    variant: WS2812
    pin: D5
    num_leds: 4
    name: "All LEDs"
    id: main_leds
    restore_mode: ALWAYS_OFF   # ensures all LEDs start off


  # Individual LED partitions
  - platform: partition
    name: "LED 1"
    segments:
      - id: main_leds
        from: 0
        to: 0

  - platform: partition
    name: "LED 2"
    segments:
      - id: main_leds
        from: 1
        to: 1

  - platform: partition
    name: "LED 3"
    segments:
      - id: main_leds
        from: 2
        to: 2

  - platform: partition
    name: "LED 4"
    segments:
      - id: main_leds
        from: 3
        to: 3


# Physical button on D6 to turn off all LEDs
binary_sensor:
  - platform: gpio
    pin:
      number: D6
      mode: INPUT_PULLUP
      inverted: True
    name: "All Off Button"
    on_press:
      - logger.log: "Button pressed — turning all LEDs OFF"
      - light.turn_off: main_leds

Home Assistant automation:

alias: Afvalwijzer Plastic
description: Afvalwijzer leds
triggers:
  - at: "18:00:00"
    trigger: time
conditions:
  - condition: template
    value_template: >
      {% set raw = states('sensor.gad_pmd') %} {% if raw not in ['unknown',
      'unavailable', 'none', ''] %}
        {% set clean = raw.replace('Tomorrow, ', '').replace('Today, ', '').strip() %}
        {% set parts = clean.split(', ') %}
        {% set date_part = parts[-1] if parts|length > 1 else clean %}
        {% set pmd_date = strptime(date_part, '%d-%m-%Y').date() %}
        {% set tomorrow = (now().date() + timedelta(days=1)) %}
        {{ pmd_date == tomorrow }}
      {% else %}
        false
      {% endif %}
actions:
  - action: light.turn_on
    target:
      entity_id: light.afvalwemos_led_3
    data:
      rgb_color:
        - 236
        - 199
        - 14
mode: single