All posts by fash

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());  

BLD-305S and Arduino

Part of a client’s build for powerful DC motors, so no details

Controlling this with an Arduino is straightforward, except for the SV signal.

This controls the speed using a voltage level.
A Uno has analog inputs, no outputs.

The trick is using a digital potmeter.

256 steps potmeter MCP41100

#include <SPI.h>
int svpin = 5;
setup:
  pinMode(svpin, OUTPUT);

loop:
// SPI Digital potmeter
  digitalPotWrite(0x20);

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.

Started using FreeCad

FreeCAD is an open-source parametric 3D modeller made primarily to design real-life objects of any size. Parametric modelling allows you to easily modify your design by going back into your model history and changing its parameters.

Designed a case for a measure tool, I’ve printed a case for a while ago.

What are my thoughts : I like it, I like the setup, workbench and the fact that you can edit every step again.

Measure diameter case using 3D printed tool

Draw case using FreeCAD

A 3D CAD mouse helps!

Uncleanable 2nd hand controller

Below, a technical drawing exported to PDF using FreeCAD

Playing around with the 3D CAD Mouse

I forgot the holes for mounting, these I did using Bambu Studio.

Busy building my new workspace but meanwhile I am playing with machine learning

I needed more space for my business, so I moved to my big workshop space where our music studio was.

I’ve installed Yolo (v8) and generated an image using ChatGPT with many objects.

Installing Yolo:
See https://docs.ultralytics.com/quickstart/#install-ultralytics

Generated image

Using below python script I get a text file with hits and an image with objectboxes.

import cv2
import random
from ultralytics import YOLO
# Load YOLOv8 model
model = YOLO('yolov8n.pt')  
input_image_path = 'input.jpg'
image = cv2.imread(input_image_path)
def get_random_color():
    return [random.randint(0, 255) for _ in range(3)]
class_colors = {i: get_random_color() for i in range(len(model.names))}
results = model(input_image_path)
output_txt_path = 'output.txt'
with open(output_txt_path, 'w') as f:
    for result in results:
        for box in result.boxes:
            cls = int(box.cls[0])  
            confidence = box.conf[0].item() 
            bbox = box.xyxy[0].cpu().numpy()
            class_name = model.names[cls]
            # Write text file
            f.write(f"Class: {class_name}, Confidence: {confidence:.2f}, BBox: {bbox}\n")
            color = class_colors[cls]
            cv2.rectangle(image, 
                          (int(bbox[0]), int(bbox[1])), 
                          (int(bbox[2]), int(bbox[3])), 
                          color, 3)  # Thicker rectangle
            label = f'{class_name} {confidence:.2f}'
            font_scale = 1.0  # Larger font size
            font_thickness = 2  # Thicker font
            cv2.putText(image, 
                        label, 
                        (int(bbox[0]), int(bbox[1]) - 10), 
                        cv2.FONT_HERSHEY_SIMPLEX, 
                        font_scale, color, font_thickness)
output_image_path = 'output_with_boxes.jpg'
cv2.imwrite(output_image_path, image)
print(f"Detected objects saved to {output_txt_path}")
print(f"Output image with boxes saved to {output_image_path}"

Text file

Class: car, Confidence: 0.91
Class: car, Confidence: 0.90
Class: giraffe, Confidence: 0.90
Class: car, Confidence: 0.87
Class: bicycle, Confidence: 0.85
Class: person, Confidence: 0.77
Class: person, Confidence: 0.68
Class: bus, Confidence: 0.66
Class: sheep, Confidence: 0.64
Class: zebra, Confidence: 0.62
Class: umbrella, Confidence: 0.60
Class: bicycle, Confidence: 0.56
Class: umbrella, Confidence: 0.54
Class: airplane, Confidence: 0.52
Class: person, Confidence: 0.51
Class: person, Confidence: 0.48
Class: bicycle, Confidence: 0.44
Class: person, Confidence: 0.43
Class: stop sign, Confidence: 0.40
Class: umbrella, Confidence: 0.39
Class: motorcycle, Confidence: 0.39
Class: bicycle, Confidence: 0.38
Class: person, Confidence: 0.37
Class: person, Confidence: 0.35
Class: teddy bear, Confidence: 0.29
Class: truck, Confidence: 0.27
Class: airplane, Confidence: 0.26
Class: bus, Confidence: 0.25
Class: person, Confidence: 0.25

Code for real-time detection using a webcam.

from ultralytics import YOLO
import cv2
import math 
# start webcam
cap = cv2.VideoCapture(0)
cap.set(3, 640)
cap.set(4, 480)
# model
model = YOLO("yolo-Weights/yolov8n.pt")
# object classes
classNames = ["person", "bicycle", "car", "motorbike", "aeroplane", "bus", "train", "truck", "boat",
              "traffic light", "fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat",
              "dog", "horse", "sheep", "cow", "elephant", "bear", "zebra", "giraffe", "backpack", "umbrella",
              "handbag", "tie", "suitcase", "frisbee", "skis", "snowboard", "sports ball", "kite", "baseball bat",
              "baseball glove", "skateboard", "surfboard", "tennis racket", "bottle", "wine glass", "cup",
              "fork", "knife", "spoon", "bowl", "banana", "apple", "sandwich", "orange", "broccoli",
              "carrot", "hot dog", "pizza", "donut", "cake", "chair", "sofa", "pottedplant", "bed",
              "diningtable", "toilet", "tvmonitor", "laptop", "mouse", "remote", "keyboard", "cell phone",
              "microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors",
              "teddy bear", "hair drier", "toothbrush"
              ]
while True:
    success, img = cap.read()
    results = model(img, stream=True)
    # coordinates
    for r in results:
        boxes = r.boxes
        for box in boxes:
            # bounding box
            x1, y1, x2, y2 = box.xyxy[0]
            x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2) # convert to int values
            # put box in cam
            cv2.rectangle(img, (x1, y1), (x2, y2), (255, 0, 255), 3)
            # confidence
            confidence = math.ceil((box.conf[0]*100))/100
            print("Confidence --->",confidence)
            # class name
            cls = int(box.cls[0])
            print("Class name -->", classNames[cls])
            # object details
            org = [x1, y1]
            font = cv2.FONT_HERSHEY_SIMPLEX
            fontScale = 1
            color = (255, 0, 0)
            thickness = 2
            cv2.putText(img, classNames[cls], org, font, fontScale, color, thickness)
    cv2.imshow('Webcam', img)
    if cv2.waitKey(1) == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

Note: generated picture is not perfect. See zebra. AI output is affected by this.

3D print fun

Multi Color !
New bottle clip, all made within bambu studio.

Resize, clone, negative boolean, selective cut, text surface, change modifier type.

Bambu studio:

I’ve made a script to view the camera using vlc. But it was much work.
Now I’ve installed the HACS Bambu integration in Home Assistant.
Much easier to get an image.

While Bambu studio is nice, I started using FreeCad.
I still use OpenScad and Blender, but I really try to use a CAD program for modeling 3D prints (technical prints). For sculpting I still use blender.