Smoker

After fooling around on my trusty Weber, i bought myself a offset smoker.

My good friend Vincent, talked me into buying a big metal beast, and i never had any regrets.

Macro Buttons

A box with macro buttons for your PC using Arduino Leonardo

#include <Keypad.h> // matrix read
#include <Keyboard.h> // keyboard out

#define ENABLE_PULLUPS // fuck the resistors
#define NUMBUTTONS 25 // matrix
#define NUMROWS 5 // matrix rows
#define NUMCOLS 5 // matrix cols

int analog1 = A3;
int analog2 = A7;


int inPinctrl = 3;  // function ctrl, pull to vcc
int inPinalt = 4;  // function alt, pull to vcc 
int valctrl = 0;    // variable to store shifter
int valalt = 0;    // variable to store shifter
int joyx = 0;
int joyy = 0;

//define the symbols per key
char buttons[NUMROWS][NUMCOLS] = {
  {'q','w','e','r','t'},
  {'y','u','i','o','p'},
  {'a','s','d','f','g'},
  {'h','j','k','l','z'},
  {'x','c','v','b','n'},
};
// q-1 (star)      e-zoomin    r-prev t-up
// y-2 u-clearstar             o-open p-down
// a-3 (rate)      d-zoomreset f-full g-left
// h-4 j-clearrate             l-esc  z-right
// x-5 c-slideshow v=zoomout   b-next

//    14 16 10 9  8 
// 21 q  y  a  h  x  
// 20 w  u  s  j  c
// 19 e  i  d  k  v 
// 18 t  p  g  z  n
// 15 r  o  f  l  b 

byte rowPins[NUMROWS] = {16,20,19,18,15}; //connect to the row pinouts of the keypad
byte colPins[NUMCOLS] = {14,7,10,9,8}; //connect to the column pinouts of the keypad

//initialize an instance of class NewKeypad
Keypad buttbx = Keypad( makeKeymap(buttons), rowPins, colPins, NUMROWS, NUMCOLS); 


void setup() {

  Serial.begin(115200); // debug out baud
  pinMode(inPinctrl, INPUT);    // sets the digital pin 3 as input
  pinMode(inPinalt, INPUT);    // sets the digital pin 4 as input
  digitalWrite(inPinctrl, HIGH);       // turn on pullup resistors
  digitalWrite(inPinalt, HIGH);       // turn on pullup resistors
  Keyboard.begin();        // keyb starter
}



void loop() { // loop the program

  CheckAllButtons(); // check tha buttons

}


void CheckAllButtons(void) {
  joyx = analogRead(analog1);
  joyy = analogRead(analog2);
  Serial.println(joyx);
  Serial.println(joyy);
  if (joyx > 900) { 
      Keyboard.press(KEY_UP_ARROW);
      delay(150);
      Keyboard.releaseAll();
  }
  if (joyx < 200) { 
      Keyboard.press(KEY_DOWN_ARROW);
      delay(150);
      Keyboard.releaseAll();      
  }
  if (joyy > 900) { 
      Keyboard.press(KEY_LEFT_ARROW);
      delay(150);
      Keyboard.releaseAll();
  }
  if (joyy < 200) { 
      Keyboard.press(KEY_RIGHT_ARROW);
      delay(150);
      Keyboard.releaseAll();
  }

  
  char key = buttbx.getKey();

  if (key != NO_KEY)  {
      valctrl = digitalRead(inPinctrl);   // read the function pin
      valalt = digitalRead(inPinalt);   // read the function pin
      Serial.write(valctrl);  // debug
      Serial.println();  // enter
      Serial.write(valalt);  // debug
      Serial.println();  // enter
      Serial.write(key);  // debug
      Serial.println();  // enter
      // button 1 
          if (key == 'q') {
            if (valctrl == 0) { // function shifter active?
               Keyboard.press(KEY_LEFT_CTRL); 
            }
            if (valalt == 0) { // function shifter active?
               Keyboard.press(KEY_LEFT_ALT); 
            }
           Keyboard.press('1');
           delay(150);
           Keyboard.releaseAll();
          }
      // button 2
          if (key == 'y') {
            if (valctrl == 0) { // function shifter active?
               Keyboard.press(KEY_LEFT_CTRL); 
            }
            if (valalt == 0) { // function shifter active?
               Keyboard.press(KEY_LEFT_ALT); 
            }
           Keyboard.press('2');
           delay(150);
           Keyboard.releaseAll();
          }
      // button 3
          if (key == 'a') {
            if (valctrl == 0) { // function shifter active?
               Keyboard.press(KEY_LEFT_CTRL); 
            }
            if (valalt == 0) { // function shifter active?
               Keyboard.press(KEY_LEFT_ALT); 
            }
           Keyboard.press('3');
           delay(150);
           Keyboard.releaseAll();
          }
      // button 4
          if (key == 'h') {
            if (valctrl == 0) { // function shifter active?
               Keyboard.press(KEY_LEFT_CTRL); 
            }
            if (valalt == 0) { // function shifter active?
               Keyboard.press(KEY_LEFT_ALT); 
            }
           Keyboard.press('4');
           delay(150);
           Keyboard.releaseAll();
          }
      // button 5
          if (key == 'x') {
            if (valctrl == 0) { // function shifter active?
               Keyboard.press(KEY_LEFT_CTRL); 
            }
            if (valalt == 0) { // function shifter active?
               Keyboard.press(KEY_LEFT_ALT); 
            }
           Keyboard.press('5');
           delay(150);
           Keyboard.releaseAll();
          }
      // button i - clear rate
          if (key == 'i') {
           Keyboard.press(KEY_LEFT_CTRL); 
           Keyboard.press('0');
           delay(150);
           Keyboard.releaseAll();
          }
      // button k - clear label
          if (key == 'k') {
           Keyboard.press(KEY_LEFT_ALT); 
           Keyboard.press('0');
           delay(150);
           Keyboard.releaseAll();
          }
      // button v - slideshow
          if (key == 'v') {
           Keyboard.press(KEY_ESC); 
           Keyboard.press(KEY_LEFT_CTRL); 
           Keyboard.press('s');
           delay(150);
           Keyboard.releaseAll();
          }
      // button t - zoomin
          if (key == 't') {
           Keyboard.press('+'); 
           delay(150);
           Keyboard.releaseAll();
          }
      // button g - zoomreset
          if (key == 'g') {
           Keyboard.press('*');
           delay(150);
           Keyboard.releaseAll();
          }
      // button n - zoomout
          if (key == 'n') {
           Keyboard.press('-'); 
           delay(150);
           Keyboard.releaseAll();
          }
//r  o  f  l  b
      // button r - prev
          if (key == 'r') {
           Keyboard.press(KEY_LEFT_CTRL); 
           Keyboard.press(KEY_LEFT_ARROW); 
           delay(150);
           Keyboard.releaseAll();
          }
           
      // button o - open
          if (key == 'o') {
           Keyboard.press(KEY_RETURN); 
           delay(150);
           Keyboard.releaseAll();
          }
           
      // button f - full
          if (key == 'f') {
           Keyboard.press('f'); 
           delay(150);
           Keyboard.releaseAll();
          }
           
      // button l - esc
          if (key == 'l') {
           Keyboard.press(KEY_ESC); 
           delay(150);
           Keyboard.releaseAll();
          }
           
      // button b - next
          if (key == 'b') {
           Keyboard.press(KEY_LEFT_CTRL); 
           Keyboard.press(KEY_RIGHT_ARROW); 
           delay(150);
           Keyboard.releaseAll();
          }
           





          
  }
}

3D printed a stone

Why? Because i can

While on holiday in New Zealand i made photos of a rock i found on the campsite we where. Nothing special about the rock, but it was a nice subject to try to replicate.

So i took many many pictures of the stone from all sides.

Imported those images in meshroom and convered it to a 3D stl object.

Blender object

Printing and airbrushing

Added some grass from our clock project

Pressure Lab

For measuring pressure in fermentation containers, I designed a pressure sensor which could be wireless connected to a fermentation container.
The sensor would transmit the values to a Raspberry which was configured as a Access Point and would store the measurements and generated graphs using Grafana.

Raspberry with RealtimeClock
RTC on raspberry

3D printed holder, designed in blender. Holds battery prints and has little handle to lift from container

Nodes config:

Esp configuration, connect with micro-usb
Flashing with linux

esptool.py -p /dev/ttyUSB0  write_flash 0x00000  ESP_Easy_mega-20190311_normal_ESP8266_4M.bin

Make a connection with the ESP Access point

Connect esp with a power source.
Look for a AP with ESP_Easy_0

Use password “configesp” to connect

Start you browser and enter http://192.168.4.1

In wifi wizard setup select “pressurespot”
Enter password “pressurespot”

Press connect

Wait 20s and look in the raspberry logs which IP the ESP got.

Connect laptop/mobile to wifi “pressurespot”and connect

Enter found IP from ESP in your browser.

Proceed to main config

Main setting table, set the following

  • Unit name & number + append
  • SSID and WPA key pressurespot
  • Client IP block level allow all
  • Press submit

Press controller tab

Press first edit button and set following
– Protocol: domoticz http
Next set
– Controller IP : 10.42.0.1
– Toggle enabled and press submit

Resulting in:

Next we got to Hardware

I2C interface switch GPIO-4 and GPIO-5

  • GPIO – SDA: GPIO-4 (D2) change to GPIO-5 (D1)
  • GPIO – SCL: GPIO-5 (D1) change to GPIO-4 (D2)
  • Press “Submit”

Devices TAB

Press edit, and select device “Environment – BMx280” from the pulldown menu.

Next, set the following

  • Name: pressure
  • Enable on
  • I2C address : 0x76 ( Is there is no 0x76 of 0x77 .. do a i2c scan on the next tab )
  • Send to controller , mark this
  • IDX: give this the number you had given this node (this is the one you have to use in domoticz )
  • interval 10Seconds
  • and press submit

In the Devices tab, you should be able to see the sensor with the values (Temperature and pressure)

No values? Do a i2c scan and/or reboot ESP ( You can find these in the tools tab)

Tools TAB

Press I2C scan, when seeing a address like 0x76 or 0x77 use this in previous tabs.
Still nothing, even after reboot? Maybe faulty hardware?

Everything okay? Back to the config tab

We are going to set the sleep mode.
Warning ! .. when setting this it is hard to get into the config pages again.
ESP will startup, connect to wifi, send values and goes to sleep again.

At the bottom set: Sleep awake time 1 sec

Buttons on the raspberry / pressurespot

Red button :

  • Less than 3 seconds is reboot
  • Longer than 3 seconds is shut down
    • Charger can be removed, when the green light is off

Led lights on the sensors

  • Red light (R2; constant): battery is charging
  • Blue light (R1; constant): battery is full
  • Blue light (R1; constant) & red light (R2; blinking): trying to charge, but no battery connected

Add shutdown script to /etc/rc.local

python /usr/local/bin/power-switch.py &amp;

/usr/local/bin/power-switch.py

#!/usr/bin/python
import threading, subprocess
import RPi.GPIO as GPIO
def shutdown():
    subprocess.call('sudo shutdown -h now', shell=True)
def edge_detected(pin):
    if GPIO.input(pin):
        t.cancel()
        subprocess.call('sudo reboot', shell=True)
    else:
        t.start()
if __name__ == '__main__':
    try:
        GPIO.setmode(GPIO.BOARD)
        GPIO.setup(5, GPIO.IN)
        GPIO.add_event_detect(5, GPIO.BOTH, callback=edge_detected, bouncetime=10)
        t = threading.Timer(3.0, shutdown)
        while True:
            pass
    finally:
        GPIO.cleanup()

/usr/local/bin/ledoff.py

#!/usr/bin/python
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(18,GPIO.OUT)
GPIO.output(18,GPIO.LOW)

/usr/local/bin/ledon.py

#!/usr/bin/python
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(18,GPIO.OUT)
GPIO.output(18,GPIO.HIGH)

nmcli device wifi hotspot ssid pressurespot password pressurespot

 /etc/NetworkManager/system-connections/Hotspot-1

[connection]
id=Hotspot-1
uuid=c2c05528-63f9-44c7-93ce-264187a45086
type=wifi
permissions=
timestamp=1553708934

[wifi]
hidden=true
mac-address=B8:27:EB:7F:D5:E7
mac-address-blacklist=
mode=ap
seen-bssids=B8:27:EB:7F:D5:E7;
ssid=pressurespot

[wifi-security]
group=ccmp;
key-mgmt=wpa-psk
pairwise=ccmp;
proto=rsn;
psk=pressurespot

[ipv4]
dns-search=
method=shared

[ipv6]
addr-gen-mode=stable-privacy
dns-search=
method=ignore

/usr/bin/servicecheck.sh (in rc.local and crontab root user – every minute

#!/bin/bash
nmcli connection show  | grep "Hotspot-1           c2c05528-63f9-44c7-93ce-264187a45086  802-11-wireless  wlan0" &gt;/dev/null &amp;&amp; touch /tmp/wlan || rm -f /tmp/wlan
for f in influx domoticz telegraf grafana mosquitto ; do
pgrep $f &gt;/dev/null &amp;&amp; touch /tmp/$f || rm -f /tmp/$f
done
count=$(ls  /tmp/influx /tmp/domoticz /tmp/telegraf /tmp/grafana /tmp/mosquitto /tmp/wlan | wc -l)
if [ $count -eq 6 ]  ; then
/usr/local/bin/ledon.py
exit 0
fi

for timer in {1..10} ; do
/usr/local/bin/ledon.py
sleep 1

/usr/local/bin/ledoff.py
sleep 1
done

Rest services to be installed on Raspberry

At the moment the raspberry uses domoticz between the Mqtt broker (Mosquitto) and the database (Influx)
Data wil be displayed using grafana.

tail -f /var/log/syslog shows which ip to which ESP
DHCPACK(wlan0) 10.42.0.104 cc:50:e3:c4:96:61 lab-
DHCPACK(wlan0) 10.42.0.181 cc:50:e3:c4:8d:73 lab-4
DHCPACK(wlan0) 10.42.0.186 cc:50:e3:c4:9b:ef lab-1

Configuring the raspberry

Install influx and grafana

First we add Influx repositories to apt:

wget -qO- https://repos.influxdata.com/influxdb.key | sudo apt-key add -
source /etc/os-release
echo "deb https://repos.influxdata.com/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/influxdb.list

Update apt with the new repo & install.

sudo apt update && sudo apt install -y influxdb

Then start the influxdb service and set it to run at boot:

sudo systemctl enable influxdb --now

Again we need to add the Grafana packages to apt:

wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee /etc/apt/sources.list.d/grafana.list

We can now update and install the binaries:

sudo apt update && sudo apt install -y grafana

Then simply enable the service and set to run at boot:

sudo systemctl enable grafana-server.service --now

Now we can check that grafana is up by loading it in a browser: http://10.42.0.1:3000. If so, you can log in with the username and password = admin and set a new admin password.

Install mosquitto

sudo apt install mosquitto mosquitto-clients

Install domoticz using below command

<code><strong>curl -sSL install.domoticz.com | sudo bash</strong></code>

Under hardware add MQTT server adress 127.0.0.1

Add virtual sensors to domoticz.

Click hardware and create virtual sensor, lab with sensornumber. Sensor type is Temp+Baro.

When looking at devices you will see the virtual devices.

Here you can see if data is coming from the ESP’s

Pushing the data into Influxdb:

Goto settings > more options > data push > influxdb

Add temperature

  • Device name: lab* (lab plus unit number)
  • Value to send: temperature
  • Target type: direct (NOTE screenshot below is wrong)
  • press add

Add barometer

  • Device name: lab* (lab plus unit number)
  • Value to send: Barometer
  • Target type: direct (NOTE screenshot below is wrong)
  • press add

Configure Grafana

Go with your browser to http://10.42.0.1 when connected to the rpi access point

Goto settings and data sources, add influxdb with source http://localhost:8086
Goto dashboard and create a new one.

Data source is influx, select A Barometer
And the IDX that was used in configuring the ESP
Axes: Units in millibars, above example had temperature, for both Baro and Temp in one graph.
Select null value as connected

TODO

Telegraf/mosquito
Services in domoticz
Rpi status display
Sensor test / monitor

Little USB password paster

When using Spice and VNC to virtual machine consoles, and remote consoles like idrac and ilo, it is not alway possible to copy-paste.

When doing maintenance it is a annoyance to type a super strong and long password by hand, Prone to typing errors, timeouts. And following lockouts.

So i wanted to auto type the password.

First solution was to bind a little bash script to a key combination.

#!/bin/bash
# Usage: make a keypress shortcut to this script
# activate shortcut, and the script wil give you 10 seconds to click and focus remote console window.
# It pastes the password, and you can press enter to login
# ( you can use xdotool also to press enter for you )
sleep 10
xdotool type "SUP3Rl00000ngandcompl3xpasswo0d@#@#@#%$%$%%$-you-cant-type-me-without-erors"

I’ve bound this to a key combination on my workstation.

gsettings set org.gnome.settings-daemon.plugins.media-keys custom-keybindings "['/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/']"
gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/ name 'passpaste'
gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/ command '~/bin/passpaste.sh'
gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/ binding '<Super>p'

This works, but only where this script is installed.
So not on colleagues machines, workstations with windows, and the super secret admin/root account sits in a file.

So i made a password key, which count be behind lock and key.

Using a digistump, a push-button and a resistor, the passpaster was born.

Program to flash on the digistump

#include "DigiKeyboard.h"
void setup() {
  DigiKeyboard.sendKeyStroke(0);
  DigiKeyboard.delay(1000);
}

void loop() {
  if (digitalRead(0) == HIGH) WorkPass();
  if (digitalRead(1) == HIGH) LtPass();
}

void WorkPass() {
  DigiKeyboard.print("SUP3Rl00000ngandcompl3xpasswo0d@#@#@#%$%$%%$-you-cant-type-me-without-erors");
  DigiKeyboard.println();
  DigiKeyboard.delay(50);
  setup();
}

void LtPass() {
  DigiKeyboard.print("secondlongpasswordifyouareusingtwobuttons");
  DigiKeyboard.println();
  DigiKeyboard.delay(50);
  setup();
}

Plug the Digispark into you machine, it wil emulate a HID device (Keyboard).
Get your remote console into focus, press button .. presto!

TODO:

  • 3D print a little case
  • pin protect?
  • rotary + display? (Like below)

It would be nice to have something like:

Rotary encoder 1 – selects which password to paste
Rotary encoder 2 – (1-255) does a encryption method on the password
Display shows : Password #32 – Crypt # 88
So you can have for example 255 passwords with 255 encryptions .. which to use when? Only you know.

Above can’t be done with a Digispark, so i’ll have to use a Arduino Pro Mini or a equivalent

Mount Taranaki New Zealand

While traveling New Zealand we went to see Mt Taranaki

Mount Taranaki (Māori: Taranaki Maunga), also known as Mount Egmont, is a dormant stratovolcano in the Taranaki region on the west coast of New Zealand’s North Island. It is the second highest point in the North Island, after Mount Ruapehu.

I made this timelapse using a Nikon D750.

Convert a series of jpgs into a mp4

ffmpeg -f image2 -r 24 -start_number 8296 -i "750_%04d.JPG"  -vcodec libx264 -profile:v high444 -refs 16 -crf 0 -preset ultrafast -vf scale=1920:1080 output.mp4

Fixing a WD My passport not working in New Zealand

I’ve got a backup disk for my photos.
You can connect it via USB and has a SDCard slot for your camera SDCards.
You can also connect to is using it as a Wifi Access Point.
(You can even install twonky!)

The cardreader should automatically copy a inserted card to its internal harddrive.
I’ve tested this at home, but here in New Zealand it woudn’t work.

So i started investigating.
(I was in the middle of nowhere, so I could not search for answers.)

I’ve got the juice ssh client on my phone.
Connecting to the AP will give you a IP, but whats the IP from de WD?
Just use JuiceSSH to make a local connection (to your android) first.
And type: ip neigh
This will give you the ip from neighbouring devices, thats only one .. the WD.

Connect to the WD with ssh using root@IPNUMMER (password should be same as you configured the device with)

Looking at the logs gave me some idea where the problem was.

It would not mount the sdcard! Why, that one is working.
(In de Nikon Camera and using a cardreader with OTG on my android)

I first wrote my own mounter and copy program. That worked, so i could at least backup my photos.
Now I could search for the problem.

My backup script named “script”

mkdir /tmp/fash ; mount /dev/mmcblk0p1 /tmp/fash mounts okay!

The sdmount.sh has a problem, it uses the timezone in its script.
This will work when in GMT+12 -> GMT-12.
But we are in NZ .. thats GMT+13

Removing some checks in above script (sdmount.sh)
(Adding timeoffset_min=8)
Made the script work for me again.
When I got home from our trip, I flashed a new firmware version on the device, which corrected the problem.

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