Almost … friday will be the day i’ll attend May Contain Hackers. Besides the awesome villages and talks.
UPDATE: 20220727 UPDATE: 20220812
You get a hackable badge, this one is more amazing as previous versions.
I can’t wait to have a go at this cool gadget. I personally could do without the pcb fancy design.
Espressif ESP32 Wrover-E with 16MB of flash storage and paired with 8MB of PSRAM, for front-end badge computing and compatibility with the badge.team ecosystem back to the 2017 SHA badge.
Lattice ICE40UP5K FPGA for hardware-accelerated graphics and user FPGA hardware designs.
Raspberry Pi RP2040 for advanced USB communication and board management.
2Ah LiPo battery to give you a full day of fun on a charge.
16-bit DAC with stereo output to headphone socket, onboard mono speaker.
ILI9341 2.2 inch TFT display with a 240 by 320 pixel resolution.
Bosch BNO055 orientation sensor.
Bosch BME680 environmental sensor.
The usual array of addressable LEDs.
SAO and Qwiic expansion connectors, FPGA PMOD expansion, plus onboard prototyping area.
Downloadable apps, micro python, Arduino ide programming. All kinds of GPIO pins, leds buttons, sound. Check out https://hatchery.badge.team/
You can play with this virtually here! https://wokwi.com/projects/335445228923126356
So much potential! Great start for a DIY project.
I won’t post about the workings, thats all well documented online. I shall post about the hacks/findings i personally did.
UPDATE: 20220727 Made a micropython program to keep your NameTag level to the ground (Better version)
UPDATE: 20220812
Someone made a 8bit logic analyser using the pmod connector !
Below some examples and connection diagrams to control displays. More code and complete schematics will be added on this page or on a separate projects page.
UPDATE 20230119 Cost of 20×4 display in 1998
LCD
I’ve used a LCD display like this (HITACHI HD44780) on my PC in the 90s, and also written code to use this as a monitoring device on my amiga.
On Linux i used LcdProc – This module also was equiped with a serial connector
Now (2023) it is 8 euros! When bought now fl to euro 98 Euro or 107 $
Some arduino’s have embedded displays like those i’ve used for a Lora project.
No usedWifi packet monitorLora test
Other means of connecting : SPI
SPI connected display
Nextion
Nextion is a Human Machine Interface (HMI) solution combining an onboard processor and memory touch display with Nextion Editor software for HMI GUI project development.
Using the Nextion Editor software, you can quickly develop the HMI GUI by drag-and-drop components (graphics, text, button, slider, etc.) and ASCII text-based instructions for coding how components interact on the display side.
Nextion HMI display connects to peripheral MCU via TTL Serial (5V, TX, RX, GND) to provide event notifications that peripheral MCU can act on, the peripheral MCU can easily update progress, and status back to Nextion display utilizing simple ASCII text-based instructions.
edit cmdline.txt
add "fbcon=map:10 fbcon=font:ProFont6x11 logo.nologo"
at the end
edit config.txt
add between custom comments at the bottom
dtoverlay=piscreen,speed=24000000,rotate=90
# Or check http://www.lcdwiki.com/3.5inch_RPi_Display
Above display’s i’ve used for Picore Players and the Lidar POC
To try: Getting above display running with a arduino https://github.com/PaulStoffregen/XPT2046_Touchscreen
Raspberry HDMI display
Easiest of them all, just connect with HDMI, there is a adaptor for hdmi-hdmi (versions 1,2,3) and hdmi-mini-hdmi for RPi4 variants.
Epaper and 7-Segment displays
Other means of displaying information are for example
Epaper
ESP with epaper module, disconnected power for a while, artifacts appear.
7 Segment displays
I used a lot of 7-Segment display’s in the past. They look cool and are hardcore.
My homebrew computer uses this
Nixie tubes!
And there are https://en.wikipedia.org/wiki/Nixie_tube .. I’ve never had those
Above bigger 2D display i used with Wled and a digital microphone, so its sound reactive. The lower part i got in recently .
I got my DIY timelapse slider out of storage, and notished it wasn’t working any more. I’t was a quick and dirty build, using minimal components and could be build with minimal effort. We could not take a lot of stuff with us to New Zealand. Camera and powerbanks, those we always take with us. So i only needed:
Raspberry Pi
Steppermotor and a plastic sheet where it was mounted on (using tiewraps you can undo)
Timingbeld
Two metal feet it was mounted on
It had to be build strong enough to hold a Nikon 750, and didn’t get out of balance when moving the camera on two metal tubes i bought in NZ.
The RPI would not start anymore, just a red power smd led. SO it didn’t boot. Taking the mini sdcard out of the raspberry trying to put it in my cardreader .. note the trying part. The damn thing broke into two parts, never seen anything like it. Damn, did i backup the latest version? No, i used my mobile and wifi in NZ to modify the scripts. Well .. “We can rebuild him, we have the technology”
How does it work?
Stepper motors move my camera over two metal rods, with ball bearing wheels. The raspberry controls my nikon using a usb cable. Mounted on the raspberry is a steppermotor hat (adafruit) which can control DC motors and stepper motors. ( In this project i used only one stepper ) The stepper motor carries the platform containing itself, a raspberry and my nikon over the “rails” Two switches on each side sends a signal to the program to stop. All timing are set via the Webgui.
Steps
At reboot, python script wil be started
Moving platform to the left, until switch detects the edge
Waiting for in structions
Entering for example timer 30, speed 10 and r
Platform wil move distance 10 to the right
Wait 30 seconds
Grab a picture
And loops until end of rod reached, then it wil move to left again.
Notes:
Gphoto works with other camera’s also
When placing the camera on the platform, focus once. Disable autofocus, also put your camera in manual mode, setting Apeture, ISO and shutterspeed same as your test photo. (bear in mind: when doing sundown shots maybe start with a little light over compensation)
Below old 2018 version
At home testingVersion i can take appartDrinking beer in NewZealand
New Sdcard. Format, put lite on this
# install gphoto2
apt-get install photo2
# connect nikon with usb, capture test with
gphoto2 --capture-image-and-download --interval 5
# Next steppers
apt-get install python3-pip
pip3 install adafruit-circuitpython-motorkit
# enable I2C
raspi-config -> enable i2c
reboot
# Test python script
import time
import board
from adafruit_motorkit import MotorKit
kit = MotorKit(i2c=board.I2C())
for i in range(100):
kit.stepper1.onestep()
time.sleep(0.01)
# Create a API
apt-get install python3-flask python3-flaskext.wtf
I’m using my phone in Hotspot mode, Timelapser will connect to my phone. Open a browser and enter : http://<ip of timelapser>:8080/form
timer in seconds to shoot pictures speed is the movement on the rail go = r(ight) or l(eft) go + timer 0, move until you reach the end (switch detect)
Todo: Need to change CSS to mobile responsive gui .. like my quizzer
import time
import subprocess
from flask import Flask, jsonify
from multiprocessing import Process, Value
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField, TextAreaField
from wtforms.validators import DataRequired
from flask import Flask, render_template, request
from flask import render_template
import board
from adafruit_motor import stepper
from adafruit_motorkit import MotorKit
import RPi.GPIO as GPIO
import os; myenv = os.environ.copy(); myenv["LANG"] = "C"
# NOTE:
# timer = seconds between shots
# speed = distance stepper travel
# Using gpio pins to detect max left/right with switches
# BCM Numbering
GPIO.setmode(GPIO.BCM)
# pullup to 17 & 18
GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)
# Stepper HAT is i2c
kit = MotorKit(i2c=board.I2C())
kit.stepper1.release()
global timer
global speed
timer=0
speed=0
go="nix"
app = Flask(__name__)
app.config['SECRET_KEY'] = 'you-will-never-guess'
class FormForm(FlaskForm):
timer = StringField('timer', validators=[DataRequired()])
speed = StringField('speed', validators=[DataRequired()])
go = StringField('go', validators=[DataRequired()])
submit = SubmitField('Send control')
# Make below in something like : nikon record .. slowly 10s to the right and recording stop?
# Or bounch left/right using gpio sensors
@app.route("/control/<time>/<speed>")
def action(number, message):
time.sleep(1)
# Print form on: http://<IP>:8080/form = start page
@app.route("/form")
def form():
form = FormForm()
return render_template('web.html', title='Web slide control', form=form)
# process form
@app.route('/data', methods = ['POST', 'GET'])
def data():
if request.method == 'GET':
return "The URL /data is accessed directly. Try going to '/form' to submit form"
if request.method == 'POST':
timer = request.form['timer']
speed = request.form['speed']
go = request.form['go']
timer = int(timer)
speed = int(speed)
if timer == 0:
print("Turn off")
p = Process(target=record_loop, args=(False,speed,timer,go))
p.start()
if str(go) == "l":
while GPIO.input(17) == True:
kit.stepper1.onestep(direction=stepper.FORWARD)
time.sleep(0.01)
if str(go) == "r":
while GPIO.input(18) == True:
kit.stepper1.onestep(direction=stepper.BACKWARD, style=stepper.DOUBLE)
time.sleep(0.01)
else:
print("Turn on")
p = Process(target=record_loop, args=(True,speed,timer,go))
p.start()
# print form again
form = FormForm()
return render_template('web.html', title='Web slide control', form=form)
# main loop, controls stepper and camera
def record_loop(loop_on,myspeed,mytimer,mygo):
while True:
if loop_on == True:
# test if switch hit yet, else move
print('timer' + str(mytimer))
print('speed' + str(myspeed))
time.sleep(2)
if str(mygo) == "l":
if GPIO.input(17):
print("Pin 17 is HIGH")
for i in range(myspeed):
kit.stepper1.onestep(direction=stepper.FORWARD, style=stepper.DOUBLE)
time.sleep(0.01)
kit.stepper1.release()
else:
print("Pin 17 is LOW")
if str(mygo) == "r":
if GPIO.input(18):
print("Pin 18 is HIGH")
for i in range(myspeed):
kit.stepper1.onestep(direction=stepper.BACKWARD, style=stepper.DOUBLE)
time.sleep(0.01)
kit.stepper1.release()
else:
print("Pin 18 is LOW")
time.sleep(mytimer)
subprocess.run(['/root/mycapture'])
subprocess.Popen([
"gphoto2",
"--capture-image"],stdout=subprocess.PIPE)
# Main loop
if __name__ == "__main__":
while GPIO.input(17) == True:
kit.stepper1.onestep(direction=stepper.FORWARD, style=stepper.DOUBLE)
time.sleep(0.01)
kit.stepper1.release()
p = Process(target=record_loop, args=(False,0,0,go))
p.start()
app.run(host='0.0.0.0', port=8080, debug=False)
p.join()
Other files
cat templates/web.html
{% block content %}
<h1>Slide control</h1>
<form action="/data" method = "POST">
{{ form.hidden_tag() }}
<p>
{{ form.timer.label }}<br>
{{ form.timer(size=32) }}
</p>
<p>
{{ form.speed.label }}<br>
{{ form.speed(size=32) }}
</p>
<p>
{{ form.speed.go }}<br>
{{ form.go(size=32) }}
</p>
<p>{{ form.submit() }}</p>
</form>
{% endblock %}
gphoto running from cron/python is a b*tch, had to rewrite subprocess and running from screen
Start screen @reboot, just crontab -e
Example is using my ledserver, see other post, but i intent to made a easy to configure node red panel where the to be controlled devices are preconfigured.
When running scripts which take a long time, i don’t want to wait for things to finish before i can start the next one.
For example, using my dedup script or compiling stuff. I wanna know when it is finished.
So i made some scripts
Maybe you can hear the spoken text in the background playing downstairs
I’ve put a function in .bashrc, so i can use a command like notify “Compiling is ready” A command like this i can put at the end of a command or in a script file at the end. make && make install && notify “compile ready”
What does it do when executed?
Send a mqtt message to the broker
Node-red will read this message and:
Send a message to my display on my desk – Sound and message notification. (See another post how i made this )
Send a message to a script on my Domoticz instance downstairs.
This will use a script to get a speech file from google, and play this on some small speakers in my livingroom
Send a pushover message to my phone
Display a message on my TV ( not in code below )
How?
At the end of your .bashrc
function notify() {
if [ -z "$1" ]; then
echo "Usage: $0 \"message\"";
exit 1;
fi
mosquitto_pub -h 10.1.0.17 -t notify/bashscript -m "$1"
}
This script will look for a cached audiofile with requested text, and uses that. Else it wil request a audio file from google, caches it and plays it though the speakers.
#!/bin/bash
INPUT=$*
input2=$(echo $INPUT | base64)
echo "$input2 = $INPUT" >> /home/pi/cache/files-text-relation
if [ -f /home/pi/cache/$input2.mp3 ] ; then
mpg123 -q /home/pi/cache/$input2.mp3 1>/dev/null 2>/dev/null
else
echo not cached
STRINGNUM=0
ary=($INPUT)
for key in "${!ary[@]}"
do
SHORTTMP[$STRINGNUM]="${SHORTTMP[$STRINGNUM]} ${ary[$key]}"
LENGTH=$(echo ${#SHORTTMP[$STRINGNUM]})
#echo "word:$key, ${ary[$key]}"
#echo "adding to: $STRINGNUM"
if [[ "$LENGTH" -lt "100" ]]; then
#echo starting new line
SHORT[$STRINGNUM]=${SHORTTMP[$STRINGNUM]}
else
STRINGNUM=$(($STRINGNUM+1))
SHORTTMP[$STRINGNUM]="${ary[$key]}"
SHORT[$STRINGNUM]="${ary[$key]}"
fi
done
for key in "${!SHORT[@]}"
do
echo "Playing line: $(($key+1)) of $(($STRINGNUM+1))"
NEXTURL=$(echo ${SHORT[$key]} | xxd -plain | tr -d '\n' | sed 's/\(..\)/%\1/g')
echo $NEXTURL
mpg123 -w $input2 -q "http://translate.google.com/translate_tts?ie=UTF-8&client=tw-ob&q=$NEXTURL&tl=En-us"
ffmpeg -i $input2 -codec:a libmp3lame -qscale:a 2 /home/pi/cache/$input2.mp3
mpg123 /home/pi/cache/$input2.mp3
done
fi
Script NO1: Below is a script which checks all sensors and switches available on my domoticz instance, and gives me information about last updates. For example when a device is out of reach or battery empty.
Usage:
Outputs to console, or you can use it in check_mk monitoring. (For the latter, create a script
vi /usr/lib/check_mk_agent/local/checkfrontdoor
chmod +x /usr/lib/check_mk_agent/local/checkfrontdoor
put in the script
#!/bin/bash
cd /path/to/script/
./belowscript "Frontdoor" 300 checkmk
Code:
#!/bin/bash
#set -x
# after running once check stateseconds for names
if [ $# -eq 0 ]; then
echo "$(basename $0) - without options .. getting states"
echo "use $(basename $0) "Sensorname" seconds" for check
echo "Getting all states"
: > stateseconds
curl -s -i -H "Accept: application/json" "http://127.0.0.1:8080/json.htm?type=devices&filter=all&used=true&order=Name" | egrep "Name|Last" | grep -v HardwareName |grep -vi levelnames> states
sed -i 'N;s/\n/,/' states
now=$(date +%s)
cat states | awk '{ print $3" "$4$7$8$9$10$11$12 }' | sed s/,,/,/g |rev | cut -c2- | rev | while read ; do
name="$(echo $REPLY | cut -f2 -d, )"
dater="$(echo $REPLY | cut -f1 -d, | sed s/\"//g)"
#echo $dater
seen=$(date -d "$dater" +%s)
#echo $seen
echo "$name $(( $now - $seen))" >> stateseconds
echo -n "."
done
fi
echo ""
if [[ ! -z "$1" && ! -z $2 ]]; then
checkold=$(cat stateseconds | grep "$1\"" | head -1 | awk '{ print $2 }')
total=$(( checkold - $2 ))
if [ -z $3 ] ; then
if [ $checkold -gt $2 ] ; then echo "$name lastseen longer than $2 seconds ago ($total sec)" ; exit 1 ;fi
else
if [ $checkold -gt $2 ] ; then echo "2 \"$1\" - Sensor older than $2 seconds" ; exit 1
else
echo "0 \"$1\" - Sensor age ok" ; exit 0
fi
fi
fi
Today Vincent mentioned a link about mqtt and mikrotiks, i knew about addons, but not mqtt .. lets try this.
When you want to use MQTT with Mikrotik you have to install the iot package from extra_packages.
Download correct package zip from ( https://mikrotik.com/download )
Download extra packages zip for your system
Extract and use file upload
Reboot your mikrotik
(i had to upgrade my firmware first, iot package was not build for my version)
Create a entry in IoT > Mqtt to your broker.
save below in a script ending with a .rsc extention, and upload in file manager
# Required packages: iot
################ Configuration #################
# Name of an existing MQTT broker that should be used for publishing, the one you just created
:local broker "10.1.0.17"
# MQTT topic where the message should be published
# i've got mine in a tree called mikrotik/switchtype/
:local topic "mikrotik/rb2011/topic"
############### System ###############
# You can create your own variables below
:put ("[*] Gathering system info...")
:local cpuLoad [/system resource get cpu-load]
:local freeMemory [/system resource get free-memory]
:local usedMemory ([/system resource get total-memory] - $freeMemory)
:local rosVersion [/system package get value-name=version \
[/system package find where name ~ "^routeros"]]
:local model [/system routerboard get value-name=model]
:local serialNumber [/system routerboard get value-name=serial-number]
:local upTime [/system resource get uptime]
################## MQTT ###################
# create a message
:local message \
"{\"model\":\"$model\",\
\"sn\":\"$serialNumber\",\
\"ros\":\"$rosVersion\",\
\"cpu\":$cpuLoad,\
\"umem\":$usedMemory,\
\"fmem\":$freeMemory,\
\"uptime\":\"$upTime\"}"
:log info "$message";
:put ("[*] Total message size: $[:len $message] bytes")
:put ("[*] Sending message to MQTT broker...")
/iot mqtt publish broker=$broker topic=$topic message=$message
:put ("[*] Done")
Import script using
import mikrotikmqtt.rsc
Todo’s:
Import is just @ import time, need to “cron” this?
"If something is worth doing, it's worth overdoing."