Tag Archives: programming

Infrared Sending Receiving

I’ve build a IR Blaster in the past and tested IR with EspEasy Dev.
I’m not happy with my Harmony Hub. Not so much control as i like to have.

So now OpenMqttGateway with IR.

I’ve installed platformio in the past.
Not really a fan of visual-code i’m showing you the process on CLI

We can’t use the webinstaller or a precompiled binary because we need to change GPIO ports

wget https://github.com/1technophile/OpenMQTTGateway/releases/download/v1.5.0/nodemcuv2-ir-libraries.zip
wget https://github.com/1technophile/OpenMQTTGateway/archive/refs/tags/v1.5.0.tar.gz
tar xzvf v1.5.0.tar.gz
cd v1.5.0/libs
unzip ../../nodemcuv2-ir-libraries.zip
cd ..
edit platformio.ini
remove ; from 
default_envs = nodemcuv2-ir
vi main/config_IR.h
search for LOLIN, edit and change into 0 (GPIO 0 = D3)

build and upload
pio run --target upload --upload-port /dev/ttyUSB0
build and upload with flash erase
pio run --target erase --target upload --upload-port /dev/ttyUSB0

clean the environment when needed
pio run -t clean

Now you will get a Access Point, connect and enter your Wifi network information and mqtt server.

When connected you will see the IR codes and if you installed mqtt support in home assistant it will see the mqtt topics.

I’ve copied a json output as was send by my IR remote.
Below an example using mosquitto_pub to send codes.

mosquitto_pub -t home/OpenMQTTGateway_ESP8266_IR/commands/MQTTtoIR -h mymqttserver -m '{
  "value": 1270235327,
  "protocol": 3,
  "bits": 32,
  "hex": "0x4BB640BF",
  "protocol_name": "NEC",
  "raw": "8908,4498,536,604,510,1700,532,604,512,604,510,1722,510,604,510,1700,534,1700,534,1702,532,606,510,1722,510,1700,534,604,512,1722,510,1722,510,604,512,604,510,1702,532,606,510,606,510,604,510,604,512,604,512,604,510,1722,510,606,510,1722,510,1702,532,1700,534,1722,512,1722,510,1700,534"
}'

platformio commands

Why use platformio?
I know Arduino IDE is easier for starters.
Platformio is far more flexible, you can make projects with their own versions of libraries.
I like CLI, easier to do version control (git)

pip install -U platformio
pio upgrade
pio update

Some screenshots of my visual code platformio

Wemos with Keypad, led and 7 segment display using MQTT

Warning, read the notes!

There are several caveats.

  • I was needing ALL GPIO pins, even RX/TX ( see trick below)
    When doing so, you can’t use serialprint.
    Do NOT enable, your sketch won’t work!
  • Don’t use pullup on D8, you can’t upload to the wemos if you do that
  • Due to library conflicts in keypad.h, DON’T change the order in the source. You will end up with compile errors!
  • The keypad has a weird pinout, but there are similar keypads with alternative layouts. Measure this using a multimeter.
  • The pull-up resistors will help fighting ghost key presses!
  • I2C needs D1/D2

To use RX/TX as GPIO pins you need to do the following:

//Define pins
  int led = 1; //tx
  int col = 3; //rx

// Change to function mode 3
// see https://www.esp8266.com/wiki/doku.php?id=esp8266_gpio_pin_allocations
  pinMode(1, FUNCTION_3);
  pinMode(3, FUNCTION_3);
 
// Revert to normal mode
// pinMode(1, FUNCTION0);

// Define mode input/output
// i'm using led to control the led so thats an output
// I'm using col for the keypad column scanner, that's an input
  pinMode(led, OUTPUT);
  pinMode(col, INPUT);

Complete code

The (*) clears input
The (#) sends the pin code using MQTT

Sending a 0 or 1 to escape/keypadin topic will toggle the led

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <WiFiClient.h>
// Do not change order!
#include "Keypad.h"
#include <TM1637Display.h>
#include <Ethernet.h>

#define wifi_ssid "SSID"
#define wifi_password "SSIDPASS"
#define mqtt_server "MQTTSERVER"
#define mqtt_port 1883

#define MSG_BUFFER_SIZE  (50)
char msg[MSG_BUFFER_SIZE];
int value = 0;

const byte ROWS = 4; //four rows
const byte COLS = 3; //four columns

int led = 1; //tx
int col = 3; //rx

#define CLK D1
#define DIO D2
#define TEST_DELAY   2000
TM1637Display display(CLK, DIO);

char keys[ROWS][COLS] = {
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};
byte rowPins[ROWS] = {D3, D5 , D6 , D7 };
byte colPins[COLS] = {D4 , col, D8 };

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
int keyNum = 0;
WiFiClient espClient;
EthernetClient ethClient;

PubSubClient mqtt(espClient);

void setup_wifi() {
  delay(10);
  WiFi.mode(WIFI_STA);
  WiFi.begin(wifi_ssid, wifi_password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
}


void setup() {
  setup_wifi();
  mqtt.setServer(mqtt_server, mqtt_port);
  mqtt.setCallback(callback);
  
  pinMode(1, FUNCTION_3);
  pinMode(3, FUNCTION_3);
  pinMode(led, OUTPUT);
  pinMode(col, INPUT);
  // using above? .. then disable serial!
  // Serial.begin(9600);
display.showNumberDec(0, true);
delay(TEST_DELAY);
WiFiClient espClient;
PubSubClient mqtt(espClient);

 mqtt.setClient(espClient);
 mqtt.setServer(mqtt_server, 1883);
    
mqtt.setCallback(callback);
mqtt.subscribe("escape/keypadin");

}

void callback(char* topic, byte* payload, unsigned int length) {
    //  digitalWrite(led, HIGH);

    String topicStr = topic;
      byte value = atoi((char*)payload);
       if (value == 1){
    digitalWrite(led, HIGH);

 }else if (value == 0){
    digitalWrite(led, LOW);
 }
    

}

void reconnect() {
  while (!mqtt.connected()) {
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    if (mqtt.connect(clientId.c_str())) {
      mqtt.publish("outTopic", "hello world");
      mqtt.subscribe("escape/keypadin");
    } else {
      delay(5000);
    }
  }
}



void loop() {

  if (!mqtt.connected()) {
    reconnect();
  }
    mqtt.loop();

  // put your main code here, to run repeatedly:
  char key = keypad.getKey();

  if (key) {

    if(key=='*'){
      keyNum = 0;
    } else if (key=='#'){
         ++value;
  snprintf (msg, MSG_BUFFER_SIZE, "#%1d", keyNum);
        mqtt.publish("escape/keypad", msg);
    }
    
       else{
      if(keyNum<=999){
        keyNum = (keyNum*10) + (int(key)-48);
      }
    }
    
    //  Serial.println(key);
    display.setBrightness(0x0f);

    uint8_t data[] = { 0x0, 0x0, 0x0, 0x0 };
    display.setSegments(data);

    display.setSegments(data);
    display.showNumberDec(keyNum);

  }

}

Locate and delete file copies

A simple script to locate files and select which to delete.
Uses md5sum to compare
(just be sure locatedb is up to date!)

./locatemd5 VID_20130926_211302.mp4
1 : 125a65e830c1f3654714daa0f8a41699  /tank/Backup/Nae Bother Drive/Movies/VID_20130926_211302.mp4
2 : 125a65e830c1f3654714daa0f8a41699  /tank/Backup/rclonegdrive/Nae Bother Drive/Movies/VID_20130926_211302.mp4
3 : 125a65e830c1f3654714daa0f8a41699  /tank/Private/Henri/_All online drives/Google Drive Henri/Nae Bother Drive/Movies/VID_20130926_211302.mp4
4 : 125a65e830c1f3654714daa0f8a41699  /tank/Private/gfx/Gsm/GSM Henri/nexus/2013/20130926/VID_20130926_211302.mp4
5 : 125a65e830c1f3654714daa0f8a41699  /tank/Private/Work Directory/Sorted/movies/own/VID_20130926_211302.mp4
6 : 82cd340b2b54d3ef65a02c8f31b04970  /tank/Private/www/cutshort/VID_20130926_211302.mp4
---------- which to delete ---------------
1 2 3 5
delete 1 /tank/Backup/Nae Bother Drive/Movies/VID_20130926_211302.mp4
rm: remove regular file '/tank/Backup/Nae Bother Drive/Movies/VID_20130926_211302.mp4'? y
delete 2 /tank/Backup/rclonegdrive/Nae Bother Drive/Movies/VID_20130926_211302.mp4
rm: remove regular file '/tank/Backup/rclonegdrive/Nae Bother Drive/Movies/VID_20130926_211302.mp4'? y
delete 3 /tank/Private/Henri/_All online drives/Google Drive Henri/Nae Bother Drive/Movies/VID_20130926_211302.mp4
rm: remove regular file '/tank/Private/Henri/_All online drives/Google Drive Henri/Nae Bother Drive/Movies/VID_20130926_211302.mp4'? y
delete 5 /tank/Private/Work Directory/Sorted/movies/own/VID_20130926_211302.mp4
rm: remove regular file '/tank/Private/Work Directory/Sorted/movies/own/VID_20130926_211302.mp4'? y

Bash Script

#!/bin/bash
# below gets array from subshell
shopt -s lastpipe

nr=1
locate "$1" | while read file ; do
        md5sum=$(md5sum "$file")
        echo  "$nr : $md5sum"
        myArray[$nr]="$file"
        (( nr++ ))
done
echo  "---------- which to delete ---------------"
read numbers
for f in $numbers ; do
 echo "delete $f ${myArray[$f]}"
 rm -i "${myArray[$f]}"
done

Magic Mirror no more .. lets reuse the display

I never look in the mirror, so why do i need one?
The mirror foil was already ugly in the corners.
There were bumps.
Never finished a proper interface

This one was made using a touch screen, so there are always fingerprints you could see

I’m going to use the display for an in-house small Escape Room idea i have.

Only the time part still worked, but i could not find the right cables for the touch part. The buttons displayed are meaningless anyway 🙂
Just a mockup

Mirror part was done using a Safety/One way mirror foil.
Cut a part as large as you screen, spray a little water and stick it on.

At some point i displayed Dashticz on there.
Apparently i started playing with a magic mirror setup in 2015, according some timestamps of code on my fileserver.

Security cam ftp search major changes in images.

Weird title i know.

I have several ip cameras which monitor movement in and around our home.

I’m using Zoneminder and other home automation systems but i want to scan through a bunch of files uploaded by the security cameras to my secondary fileserver.

So what is interesting?

  • Major movement compared to a base image
  • Movement compared to a previous uploaded image
  • Setting a threshold when to output information (note the 65% mark)
| 76 % | 1438 | SDAlarm_20221129-213515.jpg | 3145 | .......-.......................X.....................................................................
| 76 % | 1439 | SDAlarm_20221129-213517.jpg | 3661 | ..............-.....................X................................................................
| 76 % | 1440 | SDAlarm_20221129-213519.jpg | 3739 | ...........-.........................X...............................................................
| 77 % | 1441 | SDAlarm_20221129-213521.jpg | 3704 | .....-...............................X...............................................................

Looking at the output we see:
At 76% of the captured images (image 1438) the threshold was above 3000 and the minus gives us the information of the difference between this image and the previous, the X marks the difference between current image and the baseline.
| percent | image number | filename | difference | graphbar

Bash script:

#!/bin/bash
threshold=3000
baseline=$( ls  SDAlarm*jpg | head -1)
previous=$( ls  SDAlarm*jpg | head -1)
total=$( ls *.jpg |wc -l)
echo "Number of files : $total"
nr=1
ls *jpg | while read; do
graph="....................................................................................................."
diff=$(compare -verbose -metric MAE $baseline $REPLY /dev/null  2>&1 | grep all | awk '{ print $2 }' | cut -f1 -d. )
prevdiff=$(compare -verbose -metric MAE $previous $REPLY /dev/null  2>&1 | grep all | awk '{ print $2 }' | cut -f1 -d. )
line=$( echo "100 / $total * $nr" | bc -l | cut -f1 -d.)
line=$(( $line + 1))
#echo -n "$line | $nr | $REPLY | "
#echo $diff
draw1=$(( $diff / 100 + 1))
draw2=$(( $prevdiff / 100 + 1))
graph=$(echo $graph | sed "s/./X/$draw1")
graph=$(echo $graph | sed "s/./-/$draw2")
if [ $diff -gt $threshold ] ; then
printf "| %4s %% | %3s | %30s | %5s | %102s \n" $line  $nr $REPLY $diff $graph
fi
nr=$(( $nr +1 ))
previous=$REPLY
done

Want to see only difference with previous image?

change:

if [ $diff -gt $threshold ] ; then
into
if [ $prevdiff -gt $threshold ] ; then

Tunebook generator

2023-01-11 Updated the script! More functions

I’m using below scripts to generate tunebooks.
These books I can print OR view on a tablet using my DIY bluetooth page turner. ( see other post )

I often work on tunes, add notes, text or write other versions.
So i needed a fast and simple way to re-generate a tunebook. ( hence the date on the title page and in the name, so i know whats the most recent version )
Now i have a separate tunebook for each instrument, with the same looks

What does this script?

  • Generates a title page using Latex
  • Generates a tune index, with page numbers ( works with multipage tunes )
  • Adds bookmarks to the tunes, so you can use the bookmark link in your reader.
  • Merges all pdf’s into one.
  • Sets title/author
  • Generic setup for multiple tunebooks
  • Generates ABC pdf and includes these

Todo: embed page numbers on every page?

BASH script:

#!/bin/bash
#sudo apt-get install texlive-latex-extra

### REMOVE OLD BOOKMARKS
ls *pdf | while read; do
rm -f "/tmp/$$.pdf"
cp "$REPLY" /tmp/$$.pdf
pdftk A=/tmp/$$.pdf cat A1-end output "$REPLY"
done


### GENERATE ABC 
if [ -d abc ] ; then
ls abc/*abc | while read abc ; do  abcm2ps -x -O - "$abc" | ps2pdf  -sPAPERSIZE=a4 - "$(echo  $abc | cut -f2 -d/ | sed 's/abc/pdf/g')" ;done
fi


nrpdf=$(ls *\.pdf | grep -vi index.pdf | grep -vi title.pdf | grep -v ^00  | wc -l)
echo "Tune PDFs in directory : $nrpdf"
pages=$(( $nrpdf / 126 ))
pages=$(( $pages + 1 ))
echo "Needed index pages : $pages"

# Extra pages : Number 002-999
extrapages=$( ls *pdf | egrep  ^00 | wc -l)
echo "Extra pages : $extrapages"

nr=$((  $extrapages  ))
echo "Total pages for tunes : $nr"
echo "create column page as text"
nr=$(( $nr +1 ))
echo $nr
ls *\.pdf | grep -vi index.pdf | grep -vi title.pdf | grep -v ^00 | sort | while read ; do 
echo "$nr $REPLY" 
next=$(exiftool "$REPLY" | awk -F": " '/Page Count/{print $2}')
nr=$(( $nr + $next ))
done | cut -f1,3- -d" " | cut -f1 -d. | sed s/\ a$//g | sed s/\ b$//g | pr -2 -t > /tmp/col
echo "Create Index pdf"
vim /tmp/col -c "set printfont=courier:h12"  -c":let &printheader = \" \""   -c "hardcopy > 001aIndex.ps | q"; ps2pdf 001aIndex.ps 

echo "Create title page pdf"
pdflatex "000 title.tex" 1>/dev/null

tempPDF=`mktemp`

echo -n "Add bookmarks : "
ls *\.pdf | grep -vi index.pdf | grep -vi title.pdf | grep -v ^00 | sort | while read i ; do
    bookmarkTitle=$( echo $i | cut -f2- -d" " | rev | cut -f2- -d. | rev)
    bookmarkInfo="BookmarkBegin\nBookmarkTitle: $bookmarkTitle\nBookmarkLevel: 1\nBookmarkPageNumber: 1"
    pdftk "$i" update_info_utf8 <(echo -en $bookmarkInfo) output $tempPDF >/dev/null
    mv $tempPDF "$i"
    echo -n "."
done
echo ""
set +x
#ls *\.pdf | grep ^[A-Z] | sort > /tmp/pdflist
name=$(pwd | rev | cut -f2 -d/ | rev)
echo $name
pdftk *pdf cat output "../${name}_$(date +%Y%m%d).pdf"
exiftool -Author="Henri Aanstoot" -Title="$name" "../${name}_$(date +%Y%m%d).pdf"

Needed tex file (named “000 title.tex”)

\documentclass[11pt]{report}
\usepackage[T1]{fontenc}
\usepackage{anyfontsize}
\usepackage[a4paper, total={6in, 8in}]{geometry}

\usepackage[T1]{fontenc}
\usepackage{tgbonum}

\newlength{\drop}

\begin{document}
  \begin{titlepage}
    \drop=0.1\textheight
    \centering
    \vspace*{\baselineskip}
    \rule{\textwidth}{1.6pt}\vspace*{-\baselineskip}\vspace*{2pt}
    \rule{\textwidth}{0.4pt}\\[\baselineskip]
    {\fontsize{50}{60}\selectfont Irish Tunes Test Tunebook}
    \rule{\textwidth}{0.4pt}\vspace*{-\baselineskip}\vspace{3.2pt}
    \rule{\textwidth}{1.6pt}\\[\baselineskip]
    \scshape
	{\large Tunebook}\par
    \vspace*{2\baselineskip}
    {\itshape Henri - Exampletunes\par}
    \vfill
    {\scshape generated:} \\
    \today
  \end{titlepage}
\end{document}

File naming:

000 title
001 index
002 – 099 xyz (extra pages, not in index)
100 – 999 Tunes (sorting)

000 title.pdf
001aIndex.pdf
002 tuneinfo.pdf
100 The Battle of Aughrim.pdf
101 I was born for sports.pdf
105 Cerlew Jig.pdf
110 Chanters Song.pdf
115 Gander at the Pratie Hole.pdf
120 honeymoon.pdf
125 Kitty Goes a-Milking.pdf
130 Terribus.pdf

Output from the script

 ./generatebook
Tune PDFs in directory : 8
Needed index pages : 1
Extra pages : 1
Total pages for tunes : 3
create column page as text
Create Index pdf
Create title page pdf
Add bookmarks : ........

Needed software:

pdftk, pdflatex, vim, exiftool, texlive-fonts-recommended

Assembly in Dosbox, and draw a line

Below my setup in Dosbox.
(As used 30 years ago)

First install dosbox (Linux/Windows)

download the package with used files and compilers from here:
https://media.henriaanstoot.nl/assembly.tgz

extract with tar xzvf /tmp/assembly.tgz to a directory

start dosbox and mount the directory as C

mount c /path/assembly

Run “a line”, this a batchfile which starts the editor (qedit)
When closing the file (esc – q menu)
It will compile the assembly and write out a executable

This is the batchfile

@echo off
q %1.asm
cls
masm %1.asm;
link %1.obj;
exe2bin %1.exe %1.com
echo READY!

line assembly code

    NAME lijnentrekroutine

.286

Code SEGMENT
    ASSUME CS:Code,DS:Code
org 100h
Start:
    mov ax,13h            ;set video mode
    int 10h

    mov bx,100
    mov cx,100
hiero:
    mov dx,0a000h
    mov es,dx
    mov ax,320
    mul cx
    add ax,bx
    mov di,ax
    mov al,2
    stosb
    inc bx
    inc bx
    inc cx
    cmp bx,150
    jnz hiero


    mov ah,8
    int 21h
    mov ax,3
    int 10h

    MOV AX,4C00h
    INT 21h

code ends
end start

Hercules to VGA

While playing with MuseScore….
(Typesetting some scores for Pipes and Flute)

This came in: WOOOT

Trident 8900C (1024 x768 max 512Kb)

This is a Trident VGA card. While having a 16bit ISA connector, it can work in a 8bits ISA slot.

A while ago i bought a Laser XT/3, that’s the one my parents had.
This is where i did a lot of assembly programming on.
It’s a 8086 cpu, 640K and has a Hercules/CGA graphics card.

I found loads of assembly files and i want to see if i can get it running again.
While some code was written for hercules, ( That’s the monochrome image you see in the example above ) and a few for EGA (4 colors).

Most of it was written for VGA. Probably on a later machine like a 80386?

But i know there are vga cards for 8 bit msdos computers, and i found one. ( This one is even autodetect, so no jumpers to figure out)

So i’ve put this card in the machine, turned it on, and it works!
I’ve got only 2 examples living on the harddisk of the machine, both black and white … 🙂
I have to search for interesting code in hundreds of files.

Some friends of mine, picture was taken from an amiga genlock digitizer
The intro pages of a “amiga emulator” WHERE is the rest??? (end is a cga starfield demo)

Hercules Card

There is not much info available about this card:

  • Max resolution (Hercules) : 720×348
  • 15 pin analog monitor port (CN1)
  • BIOS enabled JP1 Pins 1 & 2 closed
  • BIOS disabled JP1 Pins 2 & 3 closed
  • CGA selected SW1 On
  • MDA (Hercules) selected SW1 Off

Floppy drive boot

My friend EDK and I made some demo’s like

And a boot demo, which was able to start from a bootsector, went into a graphic mode and ran a demo with sound. Edk wrote a sector loader for this.
I have some 5.25 inch floppy disks, labelled boot demo. So i wanted to try this today …
I needed to change the boot order, so i went online to search for jumper settings.

I see a led when it tries to boot, but my disks are probably formatted 720Kb instead of 360Kb, which this drive is.

So …. TODO!

Find a 720Kb floppy drive (5.25 inch), and sort through my code!
There is a 8bit soundblaster compatible soundcard that i bidding on online, hopefully i’ll get it

Assembly and modes

I wasn’t sure how to sort the assembly code into Hercules and VGA compatible, but i used this table (There are also extended modes for higher resolutions)

mode 0x00text 40×25 gray
mode 0x01text 40×25 16 colors
mode 0x02text 80×25
mode 0x03text 80×25 16 color
mode 0x04graphics mode (CGA) 320×200
mode 0x05graphics mode (CGA) 320×200
mode 0x06graphics mode (CGA) 640×200 (B/W)
mode 0x07text 80×25 Hercules
mode 0x0Fgraphics mode 640×350? gray
mode 0x10graphics mode 640×350?
mode 0x11graphics vga 2 colors
mode 0x12graphics vga 16 colors
mode 0x13graphics 320×200 256 colors
# Set VGA mode
    mov ax,13h
    int 10h         ;screen 320x200 256 colours

# Exit VGA mode
    mov ax,3
    int 10h         ;screen  80x25 text
    mov ax,4c00h
    int 21h         ;back to DOS

Shelly Flood Sensor

I’ve had this Shelly sensor for a long time. But never posted anything about this.
Last weekend we had a -situation- in our kitchen, so what better time to test this device again!

This little disc shaped device has three metal points on its bottom side, those are the flood (water) sensors.
It stay’s in sleep mode when all’s good.
It does several things when it detects water.

  • Emits a alarm signal
  • Wakes-up wifi
    • Sends a MQTT message (when not connected to the cloud like i have)
      MQTT is a alarm message AND it wil send the temperature of the device!
  • After a while (when dry) goes back to sleep

There are connection point on the print you can use .. happy hacking!

My node-red configuration

Above is the part where the mqtt messages gets processed by Node-Red
Sending it to PushOver and my little MqttLcdNotifier

Above is the MqttLcdNotifer .. there are several parts to this

  • Top line is from shelly flood and other notifications
  • Text input puts text from the NR GUI on my TV and the LCDDisplay
    • same parts are being used by my 3D printer when the print tool is getting TO hot, or printing is finished
  • Trigger at work WAS a notification for work .. nonfunc
  • mqttlcd-button is the mqtt message send from the display (the one that i was pushing) to stop the beeping and clears the display
  • Bash notify, is as previously posted a flow which i can control from my linux machines notify “compiling complete” for example.
    This is also being broadcast from my livingroom using speakers.
    (See separate post about this)

Wellll, put this in place 2 years ago, never looked at it again .. still works

Volume is low, due to alarm sounds 🙂