Reverse engineering Epaper Arduino for own image pusher

To display quotes, changing once per hour.

There is not much to be found for Waveshare 4.2 Epaper.
Except for an Arduino web example.
( see https://www.waveshare.com/wiki/E-Paper_ESP32_Driver_Board )

I reversed engineered the workings, and created a python upload script to push images.

Original workings are a mess.
Per 4 bit of color, high-low switched in a byte.
Black and red separated.
Using a till p encoding over curl commands.

My implementation uses a python script called as:

python3 epaper-pusher.py ~/Downloads/Untitled.png
http://10.1.0.99/EPDI_
30 times something like 
http://10.1.0.99/ppppppppppppppppppppppppppppppppppppppppppppppppppppppaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppiodaLOAD_
http://10.1.0.99/NEXT_
30 times something like
http://10.1.0.99/pbcdefghijjjjjjffffffoooooooaaabbbbbbeeeedddppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppiodaLOAD_
http://10.1.0.99/SHOW_
NOTES:
a = 0000
-
-
-
p = 1111 = 15

30 lines with 1000 bytes ( ending with iodaLOAD_ )

black pixels
first block 1
second block 0

red pixels
first block 0
second block 1

white pixels
first block 1
second block 1

PIXEL Example
RBRB
BWBW

First block 
1010 - letter K
0101 - Letter F - second nibble = white

Second block
0101 - Letter F
1111 - Letter P - second nibble white

Code

from PIL import Image
import numpy
import requests

url="http://10.1.0.99/" 

black_pixels = numpy.zeros((400,300))
red_pixels = numpy.zeros((400,300))



def classify_pixel_color(pixel):
    """
    Classify a pixel as black, white, or red.
    """
    r, g, b = pixel[:3]  # Ignore alpha if present

    # Define thresholds for classification
    if r < 128 and g < 128 and b < 128:
        return 'black'
    elif r > 200 and g > 200 and b > 200:
        return 'white'
    elif r > 128 and g < 100 and b < 100:
        return 'red'
    else:
        return None

def process_image(image_path):
    """
    Process the image and classify its pixels into black, white, or red.
    """
    image = Image.open(image_path)
    image = image.convert("RGB")  # Ensure the image is in RGB mode

    width, height = image.size
    pixel_data = image.load()

    color_counts = {'black': 0, 'white': 0, 'red': 0}

    for y in range (0, 299):
        for x in range (0, 399):
            black_pixels[x][y] = 0
            red_pixels[x][y] = 0

    for y in range(299):
        for x in range(399):
            color = classify_pixel_color(pixel_data[x, y])
            if color:
                color_counts[color] += 1
                if color == 'black':
                    black_pixels[x][y] = 1;
                if color == 'red':
                    red_pixels[x][y] = 1;
                if color == 'white':
                    black_pixels[x][y] = 1;
                    red_pixels[x][y] = 1;

    return color_counts, black_pixels, red_pixels

def number_to_letter(num):
    """
    Translates a number from 0 to 15 into a corresponding letter (a-p).

    Args:
        num (int): The number to translate.

    Returns:
        str: The corresponding letter (a-p).
    """
    if 0 <= num <= 15:
        return chr(ord('a') + num)
    else:
        raise ValueError("Number must be between 0 and 15, inclusive.")

def print_array_in_chunks(array, chunk_size=1001):
    current_chunk = ""
    for item in array:
        # Convert item to string and add to the current chunk
        item_str = str(item)
        if len(current_chunk) + len(item_str) + 1 > chunk_size:
            # Print the current chunk and reset it
            current_chunk += "iodaLOAD_"
            try:
                requests.get(url + current_chunk, verify=False)
                if not response.content:  # Equivalent to expecting an empty reply
                    pass
            except requests.exceptions.RequestException as e:
                # Catch any request-related errors
                pass
            current_chunk = item_str
        else:
            # Append the item to the current chunk
            current_chunk += (item_str)
    current_chunk += "iodaLOAD_"
    # Print any remaining items in the chunk
    if current_chunk:
        try:
            requests.get(url + current_chunk, verify=False)
            if not response.content:  # Equivalent to expecting an empty reply
                pass
        except requests.exceptions.RequestException as e:
            # Catch any request-related errors
            pass
        

def switch_in_pairs(arr):
    # Loop through the array with a step of 2
    for i in range(0, len(arr) - 1, 2):
        # Swap values at index i and i+1
        arr[i], arr[i + 1] = arr[i + 1], arr[i]
    return arr

if __name__ == "__main__":
    import sys

    if len(sys.argv) < 2:
        print("Usage: python3 script.py <image_path>")
        sys.exit(1)

    image_path = sys.argv[1]
    try:
        color_counts, black_pixels, red_pixels = process_image(image_path)
        try:
            requests.get(url + "EPDI_" , verify=False)
            if not response.content:  # Equivalent to expecting an empty reply
                pass
        except requests.exceptions.RequestException as e:
            # Catch any request-related errors
            pass

        
        lines=[]
        for y in range(300):
            for x in range(0,399,4):
                first = red_pixels[x][y]
                second = red_pixels[x+1][y]
                thirth = red_pixels[x+2][y]
                fourth = red_pixels[x+3][y]
                nibble = 0
                if (first ==  1):
                        nibble = nibble + 8
                if (second ==  1):
                        nibble = nibble + 4
                if (thirth ==  1):
                        nibble = nibble + 2
                if (fourth ==  1):
                        nibble = nibble + 1
                lines.append(number_to_letter(nibble))
        switched_array = switch_in_pairs(lines)
        print_array_in_chunks(switched_array)
        try:
            requests.get(url + "NEXT_" , verify=False)
            if not response.content:  # Equivalent to expecting an empty reply
                pass
        except requests.exceptions.RequestException as e:
            # Catch any request-related errors
            pass
        lines=[]
        for y in range(300):
            for x in range(0,399,4):
                first = black_pixels[x][y]
                second = black_pixels[x+1][y]
                thirth = black_pixels[x+2][y]
                fourth = black_pixels[x+3][y]
                nibble = 0
                if (first ==  1):
                        nibble = nibble + 8
                if (second ==  1):
                        nibble = nibble + 4
                if (thirth ==  1):
                        nibble = nibble + 2
                if (fourth ==  1):
                        nibble = nibble + 1
                lines.append(number_to_letter(nibble))
        switched_array = switch_in_pairs(lines)
        print_array_in_chunks(switched_array)

        try:
            requests.get(url + "SHOW_" , verify=False)
            if not response.content:  # Equivalent to expecting an empty reply
                pass
        except requests.exceptions.RequestException as e:
            # Catch any request-related errors
            pass

    except Exception as e:
        pass

Home Assistant and Dehumidifier

A while ago, I bought a small Dehumidifier for my wine cellar.
I liked it a lot, so I bought another for our bedroom.

I saw some posts about people asking which Dehumidifier is supported by Home Assistant.
This one is. The “Eeese Otto Dehumidifier”

This works with the LocalTuya integration.

There are many examples how to integrate LocalTuya in HA which can be found easily using a search on the net. So, I’m not going to explain that.

I could not find a configuration example, that’s why I’ll post that part here.

Pre config:

  • Install App on phone to connect Tuya device to cloud (one time only)
    You need this to extract the localkey
  • Add a developer account to https://eu.platform.tuya.com/
    (Enable devices and change from Read to Control)
    (Get localkey from API Explorer, here is also a hint to be found about the entities)
    See below pictures
  • Install LocalTuya to HA
End result after config

Gallery of config steps

Developer website information, where to find your credentials.
(And a list of entities)

Home Assistant Voice and OpenMqttGateway

Yesterday I got my Home Assistant Voice!

This is a Non-Cloud solution like Alexa and Google devices.
I only could play with it for a few minutes because I was working on Arduino code with an ILI9341 Display and a BME280 (Temperature/Humidity/Air pressure).

Today I got some new goodies in, one of these is a LilyGO LoRa display which works on 433 Mhz.

I flashed OpenMQTTGateway on this device.

In the past, I posted about the RFCOM Gateway using Domoticz.
This runs on a Raspberry Pi.
While looking for alternatives, I found a rtl-sdr solution.

https://github.com/merbanan/rtl_433

Using this:

But I liked the ESP32 solution more.
Now I can dismantle Domoticz, which served me well for many years.

How cool to see realtime updates!

Note: This is a receiver device only!
But I only use read-only sensors like : Door/window, doorbell, temperature/humidity and Firesensors.

These are automatically detected in Home Assistant.

No more RFXCOM with a Raspberry.

Pipe tunes

I Still got 19 posts in draft, I know, but I saw a post on Reddit about tunes being played.

(Only pipe tunes) Only the lists I could find, so incomplete. (No tunes in this list from 2022-now)
Some I’ve played for 30+ years, others only a while.

I’m going to rate these soon

1st pipeband – started here at 14 yrs
2nd pipeband – continental grade 2 band
3rd pipeband – 4th grade, teaching
4th pipeband – 4th grade, teaching and piper for the Highland Dancers

A lot of tunes are being played in all bands

Own compositions are on another page

1st Pipeband

  • 1976 Police Tattoo 1st and 2nd
  • 42nd Highlanders
  • 51st highland division, The
  • Ale is dear, The
  • Amazing Grace + Marching arrangement
  • Arrival
  • Aspen bank
  • Atholl highlanders
  • Auld lang Syne 1st & 2nd
  • Balmoral 1st and 2nd
  • Banks of the Lossie, The
  • Battle of Killiecrankie
  • Battle of the Somme, The
  • Bloody fields of flanders, The
  • Bonnie Charlie is noo awa’
  • Bonnie Galloway
  • Bonnie lass O’fyvie
  • Brown haired Maiden, The
  • Bugle Horn
  • Cabar Feidh
  • Caller herrin
  • Castle Dangerous 1st & 2nd
  • Cock o’ the north
  • Corriechollie
  • Cradle song, The
  • Crusaders March, The
  • Cullen bay (Slow,Quick & 2nd)
  • Desert Storm
  • Dovecote Park
  • Dream valley of Glendaruel
  • Earl of Mansfield, The
  • Farewell to Nigg
  • Flett from flotta
  • Flower of Scotland, The 1st &
  • Glendaruel highlanders, The
  • Going Home
  • Green hills of Tyrol, The
  • Greenwood side
  • Heights of dargai, The
  • Highland cathedral 1st & 2nd
  • Highland laddie
  • High road to Gareloch, The
  • Hills of alva, The
  • Itchy Fingers
  • Jimmy Findlater
  • Killworth hills
  • Kyle Sku 1st & 2nd
  • Lady Mackenzie of Fairburn
  • Lochanside
  • Loch Duich
  • Loch Rannoch 1st & 2nd
  • Marie’s wedding
  • Meeting of the waters, The
  • Miss Girdle
  • MRS. Flora Duncan
  • Murdo’s wedding
  • My Home
  • My lodging’s on the cold groun
  • Old rustic bridge, The
  • Paddy’s leather breeches
  • Piobaireachd of Donald Dubh
  • Pipe Dreams
  • Pipers prayer, The
  • P/M J.K. Cairns 1st,2nd
  • P/M Robert Martin
  • Pony Galop
  • Road to the Isles
  • Rose of Allandale
  • Rowan Tree, The
  • Salute to the Chieftain
  • Scotland the brave
  • Scots Royal
  • Skye boat song
  • Sweet maid of Glendaruel, The
  • Swinging highland safari
  • Teribus
  • Trumpet Voluntary
  • wee highland laddie, The
  • When the battle is over
  • Wings
  • Within a mile o’ Edinburgh toon

2nd pipe band

  • Brown haired Maid
  • Susan MacLeod
  • Donald MacLeans Farewell to Oban
  • Major David Manson
  • Maggie Cameron
  • Carradale Bay
  • The Final Fling
  • Eirnies Impact
  • Bells of Dunblane
  • Finbar Sauders
  • Grey old lady of Raasay
  • Jimmy Rollo
  • Miss drummond of Perth
  • Black watch polka
  • Megalomania
  • Shovel Tongue
  • Devil in the Kitchen
  • Hellbound Train
  • Murrays Fancy
  • Bulgarian Bandit
  • Amazing Grace
  • Highland Cathedral
  • Penny Cross cottage
  • Blustering Home
  • Cutting Bracken
  • Cullen Bay
  • Eileen MacDonald
  • Whitby Runaround
  • Troys Wedding
  • Bumpy old road
  • Desert Storm
  • Daryl Boyle
  • Drochaid Luidaid
  • Easy club reel
  • Itchy Fingers
  • Stornoway
  • Up to the line
  • Brig Snow
  • Kitty lie over
  • Angus McKinnon
  • General Montgomerey
  • Dr Ross Welcome
  • Cabar Feidh
  • Accordion Man
  • Wings
  • Lord Lovats Lament
  • 1976 Police Tattoo
  • Rowan Tree
  • Crusaders March
  • Scotland the Brave
  • Lochanside
  • Balmoral
  • PM JK Cairns
  • Collins Cattle
  • When the battle is over
  • Green hills of Tyrol
  • Brown Haired maiden
  • Highroad to Gairloch
  • Highland Laddie
  • Makays Farewell
  • Johnny Cope

3rd pipe band

  • Skye boat song
  • Brown haired maiden
  • Highland Cathedral
  • Highroad to Gareloch
  • Loudons wood and braes
  • Tail Toddle
  • Stumpie
  • Highroad to Linton
  • Hills of Caithness
  • The steamboat
  • Kenmure Lads
  • Morag of Dunvegan
  • Badge of Scotland
  • Lord Lovats Lament
  • Glendaruel Highlanders
  • 48th Highlanders of Canada
  • Highland Laddie
  • Colonel Robertson
  • Green Hills of Tyrol
  • When the battle is over
  • Lochanside
  • Magersfontein
  • Scots wha hae
  • March for Gerrit Ham
  • Flower of Scotland
  • Amazing Grace
  • Wings
  • Barren rocks of Aden
  • Wilhelmus
  • Flowers of the Forrest
  • Lochaber no more
  • Morag of Dunvegan

4th pipe band

  • Argyll Broadswords Set (Piper for the dancers)
  • Flora MacDonalds Fancy Set (Piper for the dancers)
  • Scottish Lilt (Piper for the dancers)
  • Seann Truibhas (Piper for the dancers)
  • Highland Fling Set (Piper for the dancers)
  • Sword dance (Piper for the dancers)
  • Accordeon Man
  • Amazing Grace
  • Auld Lang Syne
  • Battle of the Somme
  • Bonnie Dundee
  • Bonnie Lass o’ Fyvie
  • Brown Haired Maiden
  • Cock ‘o the North
  • Coline`s Persuasion
  • Conquest of Paradise
  • Cullen Bay
  • Dark Island
  • Farewell to Camraw
  • Flower of Scotland
  • Glasgow City Police Pipers
  • Glendaruel Highlanders
  • Going Home
  • Green hills of Tyrol, The
  • Highland Cathedral
  • Highland Laddie
  • Highroad to Gairloch
  • Itchy Fingers
  • Killworth Hills
  • Loch Lomond
  • Millenium Prayer for Peace
  • Mrs Flora Duncan
  • Mull of Kintyre
  • Murdos Wedding
  • My Home
  • Old Rustic Bridge
  • Rose of Allandale
  • Rowan Tree, The
  • Scotland the Brave
  • Skye Boat Song
  • Swinging Highland Safari
  • Teribus
  • When the Battle is Over
  • Wings
  • Within a Mile o’ Edinburgh Toon

Tapsalteerie folkband

  • Ass in the Graveyard
  • Sandy’s new Chanter
  • Boys of Brittany
  • Flower of Scotland
  • Death of a Spacepiper
  • Irish Washerwomen
  • Pumkin’s Fancy, The
  • Paddy’s Leather Breeches
  • Itchy Fingers
  • Ebb Tide
  • Atholl Highlanders
  • Jolly Beggarman
  • Roses o’ Prince Charlie, The
  • Song for a smallpipe
  • Brest St. Marc
  • Blackbird
  • Masons Apron
  • The Haunting

Nae Bother Folkband

  • Bulgarian Red
  • Busindre Reel
  • Cairn Water
  • Caledonia
  • Engine Room
  • Farewell to Uist / The Lochaber Badger
  • Hector the Hero
  • Hoolit / Electric Chopsticks
  • King’s Shilling / Highland Laddie
  • Maggie West’s Waltz
  • Morag’s Jig / Joe Wilson / Cork Hill
  • Morrison’s Jig / Drowsy Maggie
  • Passing Places / Road East / Didi’s Tune
  • Pumpkin’s Fancy / The High Drive
  • Trip to Ireland / Jutland
  • Waterbound
  • Journey to the Centre of the Celts
  • Return from Finegal / Chanter’s Song
  • The butterfly / Lochaber Dance
  • Breizh / Seagull
  • Terrortime
  • Sir john Fenwick (/ Sir Sidney Smit)
  • Turning Away (zang)
  • Devil in the Kitchen / Andy Renwicks Favourite Ferret

Own repetoire

  • Archie Beag
  • Arthur Gillies
  • Ballachullish Walkabout, The
  • Banjo Breakdown, The
  • Blackbird, The
  • Brest st. Marc
  • Bronni’s Blue Brozzi
  • Bulgarian Bandit, The
  • By the river Aoro
  • Cabar Feidth
  • Calypso Piper
  • Circassian Circle, The
  • Clan Campbell’s Gathering
  • Classical Bob
  • Clumsy Lover, The
  • Cork Hill
  • Crossing the Minch
  • Da Hee and Do
  • Dark Island, The
  • Dessert Storm
  • Donella Beaton
  • Finlay M MacRae
  • Flying Haggis
  • Gaelforce Wind
  • Galician Dance
  • Galician Jig
  • Geese in the Bog
  • Glasgow City Police Pipers
  • Hag at the Churn, The
  • Haunting, The
  • Hen and the Turkey, The
  • Isabelle Blackley
  • Jiggernaut, The
  • Kelsey’s Wee Reel
  • Kitty lie over
  • Lieut McGuire’s Jig
  • Magpie, The
  • Mason’s Apron, The
  • Megalomania
  • Miss Popple’s Reel
  • Moving Cloud
  • Not the Bunny Hop
  • Paddy o’ Rafferty
  • Pipe Major Joe Wilson
  • Pipe Major’s Nightmare, The
  • Pony Galop
  • Raigmore
  • Richard’s gone bananas
  • Road North, The Air
  • Sands of Kuwait March
  • Skylark’s Ascension, The
  • South Uist Hornpipe, The
  • Swinging Highland Safari
  • Steam Train to Mallaig
  • Steampacket, The
  • Train Journey North, The
  • Whitby Runaround, The
  • Wise Maid, The
  • Abdul’s
  • Alastair’s Vintage Bar
  • A mans a man Nae Bother Version
  • An Drochaid Chluiteach
  • Andy Renwick’s Favourite Ferret
  • Angus Stewart
  • Ass in the Graveyard
  • Bells of Dunblane
  • Bonnie Portmore
  • Bonnie Portmore zang versie
  • Brenda Stubbert
  • Bugle Horn
  • Bulgarian Red
  • Busindre Reel
  • Caledonia Nae Bother Version
  • Calypso Piper
  • Calypso Piper – Second
  • Captain Colin Campbell
  • Celtic Bolero
  • Celtic Bolero – Seconds
  • Clumsy Lover (hornpipe)
  • Clumsy Lover (jig)
  • Corkhill
  • Cullen Anderson
  • Da Hee and Do (with seconds)
  • Dinkies
  • Dirty Bee
  • Donald MacLean’s Farewell To Oban
  • Dreams of a Child
  • Ducking and Diving
  • Ebb Tide
  • Electric Chopsticks
  • E Minor End Theme
  • Engine Room
  • Frances Morton’s
  • Glasgow City Police Pipers
  • Hector the Hero
  • Hellbound train
  • Hornpipe, Afternoon at the Green Monster
  • Il Paco Grande
  • In The Kitchen
  • Itchy Fingers (8 parts)
  • Jock Broon’s 70th
  • Kirstie MacCallman’s Favourite
  • La Serenissima
  • Last Word
  • Masons Apron
  • Masons Apron – cont
  • Mhair Bhan Og (Fair Young Mary)
  • Mhair Bhan Og (Fair Young Mary) – Harmony
  • Michael Faughman’s Air
  • Mozart on the Rampage
  • Music for a found harmonium
  • On the Mash
  • An Drochaid Chluiteach
  • PM Joe Wilson
  • PM John D Burgess
  • Pony Galop
  • Pressed_For_Time
  • Richard’s gone Bananas
  • Rob’s Request
  • Rory MacLeod
  • Ruby Grant
  • Senor Celtic y el Grupo
  • SleepingTune
  • Smenco Horo
  • Song for the Smallpipe
  • Sound Of Sleat
  • Steamtrain to Mallaig
  • Terror Time
  • The Bumpy Road
  • The Countryside Ceilidh
  • The Dangling Drummer
  • The Fleshmarket Close
  • The Fourth Floor
  • The High Drive
  • The Hoolit
  • The Imps
  • The January Girl
  • The King Danced at Dawn
  • The Korgi
  • The Little Cascade
  • The Maid Behind The Bar
  • The Pumpkin’s Fancy
  • The Tourist
  • The Unrest
  • TNT
  • Top Deck in Perth
  • Touchin’ Cloth
  • We will rock you
  • Zito the bubbleman

Dance Tunes

  • Devil in the Kitchen
  • Orange and Blue
  • Ghillie Calum Strathspey
  • Ghillie Calum Reel
  • Rose among the Heather
  • Piper of Drummond
  • Three Girls of Portree
  • Battle of the Somme, The
  • Flora macdonalds fancy

Display work

While working on a client project, I tested multiple displays.

  • ILI9341
  • 1.3inch SPI TFT LCD Display RGB (ST7789)
  • Waveshare 4.2 Epaper with ESP32 Controller

I thought it was fun to connect the Epaper to ESPHome.

This probably ends up being a Quote displayer
Universal e-Paper Driver Board with WiFi / Bluetooth SoC ESP32 onboard, supports various Waveshare SPI e-Paper raw panels

It was not without problems. For example, the ESPHome editor gave squiggly lines under type.
This has to be changed in the libraries.
(Already notified developers)

model: 4.20in-V2 does not work .. use model: 4.20in-v2

esphome:
  name: epaperqoute
  friendly_name: epaperqoute

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "tzRSzZky3Jk+hUYtiybzT90kxxxxxxxxxxxxxxxxxxxxx="

ota:
  - platform: esphome
    password: "4f127e114a7a44fxxxxxxxxxxxxxxxxxxxxx"

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

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

captive_portal:


external_components:
  - source: github://pr#6209
    components: [ waveshare_epaper ]

text_sensor:
  - platform: homeassistant
    entity_id: input_text.epaper_display_text
    id: epaper_display_text
    on_value:
      then:
        - component.update: epaperdisplay
    
spi:
  clk_pin: GPIO13
  mosi_pin: GPIO14

# Upload own ttf to a directory in esphome/fonts using file editor in Home Assistant
font:
  - file: "fonts/newspaper.ttf"
    id: tahoma
    size: 64

http_request:
  verify_ssl: false

# image test
online_image:
  - url: "https://www.henriaanstoot.nl/epapertest.png"
    id: example_image
    format: PNG

#it.image(0, 0, id(example_image));

display:
  - platform: waveshare_epaper
    id: epaperdisplay
    cs_pin: GPIO15
    dc_pin: GPIO27
    busy_pin: GPIO25
    reset_pin: GPIO26
    model: 4.20in-v2
    reset_duration: 200ms
    update_interval: never
    lambda: |
           it.printf(0, 0, id(tahoma), "%s", id(epaper_display_text).state.c_str());  

Divers …

Running into some Ubuntu machines with keyboard mouse problems after upgrading to 24.04

fix:

apt get install xserver-xorg-input-synaptics
apt get install xserver-xorg-input-all

3D printing some test models generated with AI from a photo to make some boardgame pieces.

Meanwhile, I am testing big motor controllers for a new client.

Last week I was at a friend’s place, time to make a launcher creator in bash

#!/bin/bash
#
if [ $# -lt 2 ]; then
	echo "createlauncher.sh name (path/bin) path/name"
    exit 1
fi


cat << EOF > /tmp/$1
[Desktop Entry]
Type=Application
Terminal=false
Name=$1
Icon=~/bin/icon/$1.png
Exec=$2 $3
EOF

cp /tmp/$1  ~/.local/share/applications/$1.desktop
update-desktop-database

Made a cable holder in my lab (Already modded)
Can be folded upwards.

Did a lot of work in my new lab/workshop.

Got some cool new tools in. Post later

Also working on a new arrangement for a bagpipe tune.

New tests for animatronics

Controlling windscreen wipers with Arduino for animatronics.

I was looking for a cheap solution to control movement, for example Halloween puppets.

I used a XY-160D dual 7A high amperage 12V controller to control a windscreen wiper.

Using a Arduino Uno and some simple code, I got movement out of the 12V motor.

Pins used:
Vcc – Arduino 5V
GND – Arduino GND
ENA – Arduino PWM pin
IN1 & IN2 (controls direction) – Two arduino output pins

Reconfiguring an old home automation controller.

After a long time, another post!
We have been to 4 states on the west coast of America for almost 4 weeks, after that a pneumonia kept me from doing stuff.

Slowly, I started finishing my Workshop/Lab for my new business.
So I didn’t have many things to post about.
So now I’ll post something about this Home Assistant solution, because there was not a decent post to be found about this solution.

Some history: A long time ago I made a 4 button 4 led controller with my friend Duncan.
At that time we were using Domoticz, and used a NodeMcu with ESP Easy to read the button states and made the leds act as status lights.

This is made using a NodeMCU (8266) but ESP32, Wemos, whatever will work also.
We wanted to repurpose the old NodeMCU, instead of building a new one.

So Migrating to Home Assistant:
How to install ESPHome is easy to find on the internet.

Below is an example for 4 push buttons which TOGGLE a Home Assistant entity.
And the LEDs will give a feedback of the state of an entity.

Note: There is 1 out of 4 configured like that. The other ones are generic.
One button toggles my shelly lab ledlight, and lights up a led when toggled!

switch.labled_relay_0 = shelly read state for led

on press toggle switch.shellyplug_s_0c5d08

 esphome:
  name: 4butttest
  friendly_name: 4butttest

esp8266:
  board: esp01_1m

# Enable logging
logger:

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

ota:
  - platform: esphome
    password: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

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

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

captive_portal:

output:
  - platform: gpio
    id: status_led
    pin: GPIO15

binary_sensor:
  - platform: homeassistant
    id: labledstate
    entity_id: switch.labled_relay_0
    on_state:
      then:
        - lambda: |-
            if (id(labledstate).state) {
              id(status_led).turn_on();
            } else {
              id(status_led).turn_off();
            }
  - platform: gpio
    name: "PinGPIO2"
    pin: 
      number: GPIO2
      inverted: true
    on_press:
      - homeassistant.service:
          service: homeassistant.toggle
          data:
            entity_id: switch.shellyplug_s_0c5d08
  - platform: gpio
    name: "PinGPIO0"
    pin: 
      number: GPIO0
      inverted: true
  - platform: gpio
    name: "PinGPIO3"
    pin: 
      number: GPIO3
      inverted: true
  - platform: gpio
    name: "PinGPIO1"
    pin: 
      number: GPIO1
      inverted: true

switch:
  - platform: gpio
    pin: GPIO13
    name: OutGPIO13
  - platform: gpio
    pin: GPIO12
    name: OutGPIO12
  - platform: gpio
    pin: GPIO14
    name: OutGPIO14

Left the entities and don’t forget right … give the esphome device rights to perform HA actions!

Not the best pins chosen, because of design based on old setup.
Resistors are 330 ohm (didn’ t want bright leds)

Mega PC tower and Book

I’ve printed two books using the Lulu service. (One for Tyrone)
When they arrived, I noticed some faults.
Lucky Lulu will be printing them again for me.

The book has over 500 pages and has a nice hardcover.

And I’ve been busy building a Mega Tower with 4 Motherboards.
This will have a superb processing power! .. not.
It houses some old motherboards for hardcore machine coding on real old hardware.

From top to bottom: 8088, 8086, 80386, 80484

Todo:

  • Rework on the cables
  • 3D print an information plaque on the front of each board
  • Add a control panel on each board
  • Maybe some dust cover would be nice

I can remove the boards, and place them on a table.
I’ve made some custom feet for them. Twist and lock by my own design.

Padded feet

The openscad files:

The locking is done by making the cylinder slightly oval by 0.5mm

difference(){
	difference(){
		difference(){
			difference(){
				rotate([90,30,0])
				cylinder(r=30, h=10, $fn=3);
				translate([-20,-20,0])
				cube([40,40,40]);
				}
			rotate([90,0,0])
			translate([0,0,-10])
			cylinder(r=5, h=30, $fn=200);
			translate([0,-5,-10])
			cylinder(r=7, h=30, $fn=200);
			}
		translate([18,-5,-12])
		cylinder(r=4, h=30, $fn=200);
		translate([18,-5,-22])
		cylinder(r=2.2, h=30, $fn=200);
		translate([-18,-5,-12])
		cylinder(r=4, h=30, $fn=200);

		translate([-18,-5,-22])
		cylinder(r=2.2, h=30, $fn=200);
		}
	translate([9,-20,-20])
	cube([40,40,40]);
}

Note the resize for the oval effect

resize([14,14.5,10])
cylinder(r=7, h=10, $fn=200);
translate([0,0,0])
cylinder(r=9, h=3, $fn=200);

When designing above, I also made new knobs for our stove.
Using the white dot, you can see which burner has which knob.

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