Monday, 22 June 2020

OpenScad Useful Functions

Some useful OpenScad functions / code

row = array_lookup(search, array, column)

OpenSCad doesn't support variable as such, so things need to be done recursively.
function array_lookup(query, source, column) = _array_lookup_rec(query, source, column, 0) ;
function _array_lookup_rec(query, source, column, row) =
    row>=len(source) ? len(source)-1 :
   query==source[row][column] ? row :
  _array_lookup_rec(query,source,column,row+1) ;
srcarray = [
[ "green", "apple", 5 ],
[ "green", "pear", 9 ],
[ "yellow", "banana", 5 ],
[ "ERROR", "ERROR", 0 ]
] ;
row1 = array_lookup("pear", scarray ,1) ;

i = toint(s)

This function uses recursion to work along the string.  It converts the supplied 's' to a string just in case an integer is supplied to the function.

// Safe Convert Decimal String to integer
function toint(st) = _toint_rec(str(st),0, 0) ;
function _toint_rec(st, idx, value) = (
    idx>=len(st) ? value
    : _toint_rec(st, idx+1, ( value*10 + ord(st[idx])-ord("0")) ) ) ;


This module produces a prism with a base which is X x Y and a height Z
The top edges can be moved in with the X and Y margins.
// prism base = x by y. left margin = xm1, bottom margin = ym1 etc.
module prism(x, y, xm1, xm2, ym1, ym2, z, center){
    CubePoints = [
        [ 0,  0,  0 ],  //0
        [ x, 0, 0 ],  //1
        [ x, y, 0 ],  //2
        [ 0, y, 0 ],  //3
        [ xm1,ym1, z ],  //4
        [ x-xm1, ym1, z ],  //5
        [ x-xm1, y-ym2, z ],  //6
        [ xm1, y-ym2, z ]]; //7
    CubeFaces = [
        [0,1,2,3],  // bottom
        [4,5,1,0],  // front
        [7,6,5,4],  // top
        [5,6,2,1],  // right
        [6,7,3,2],  // back
        [7,4,0,3]]; // left
    if (center) {
        translate([-x/2,-y/2,-z/2]) polyhedron(CubePoints, CubeFaces);
    } else {
        polyhedron(CubePoints, CubeFaces);
} ;

USB Webcam(s) with Raspberry Pi

Configuration Steps

Update the Pi

sudo rpi-update

Ensure the right modules are loaded

lsmod | grep uvcvideo
uvcvideo               94208  1
videobuf2_vmalloc      16384  2 uvcvideo,bcm2835_v4l2
videobuf2_v4l2         28672  5 bcm2835_isp,uvcvideo,bcm2835_codec,bcm2835_v4l2,v4l2_mem2mem
videobuf2_common       57344  6 bcm2835_isp,uvcvideo,bcm2835_codec,bcm2835_v4l2,v4l2_mem2mem,videobuf2_v4l2
videodev              237568  8 bcm2835_isp,uvcvideo,bcm2835_codec,videobuf2_common,bcm2835_v4l2,v4l2_mem2mem,videobuf2_v4l2
mc                     45056  8 bcm2835_isp,uvcvideo,bcm2835_codec,snd_usb_audio,videobuf2_common,videodev,v4l2_mem2mem,videobuf2_v4l2
ls -la /dev/video?
crw-rw-rw- 1 root video 81, 0 Jun 22 14:17 /dev/video0
crw-rw-rw- 1 root video 81, 1 Jun 22 14:17 /dev/video1

Add any missing modules to  /etc/modules-load.d/video.conf

e.g.:  snd-bcm2835,  i2c-dev,  bcm2835-v4l2, uvcvideo

Disable PI (non USB) camera



In order for this to work, the /dev/video0 port must exist and be accessible.

Ensure the USB video is not blacklisted

sudo rm /etc/modprobe.d/ubcvideo-blacklist.conf

Ensure the port is accessible

chmod ugo+rw /dev/video?

(this is crude - the proper thing to do is ensure that the users accessing the camera are in the 'video' group).

Programs that use the camera

uv4l - conferencing tool
motion - security camera tool
ffmpeg - video streaming


Note that motion supports video, but not audio.  This example configures it for streaming, and disables the local snapshots.

sudo apt-get install motion

vi /etc/motion/motion.conf
daemon on
output_pictures off
output_debug_pictures off
ffmpeg_output_movies off
ffmpeg_output_debug_movies off
ffmpeg_video_codec mpeg4
stream_localhost off
webcam_localhost off
camera_id = 1
videodevice /dev/video0
input -1
width W
height H
framerate F
v4l2_palette P
stream_port 8091

W,H,F,P characteristics can be identified with: ffmpeg -hide_banner -f v4l2 -list_formats all -i /dev/video0
Compressed: mjpeg : Motion-JPEG : 1920x1080 1280x720 640x360 1920x1080
Raw :  yuyv422 :  YUYV 4:2:2 : 640x360
Options for P are found in the comments in motion.conf
MJPEG = 8, YUYV = 15
The next camera goes in camera2.conf - It's videodevice will be /dev/video2 (not /dev/video1).  Make sure you pick a different ID and stream port.

Enable motion daemon
# sudo vi /etc/default/motion
Start motion
# systemctl enable motion
Check log files:
tail /var/log/syslog


Building and Installing

Setup for cross-compiling on Linux PC
sudo apt-get install build-essential git-core
sudo git clone /opt/tools
Fetch Repositories and ready for build
git clone git://
cd ffmpeg
git clone
git clone
export CCPREFIX="/opt/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-"
Build ffmpeg and libraries
# Build x264
cd x264
./configure --host=arm-linux --cross-prefix=${CCPREFIX} --enable-static --disabl
cd ..
# Build ffmpeg with x264
./configure --enable-cross-compile --cross-prefix=${CCPREFIX} --arch=armel --target-os=linux --enable-gpl --enab
le-libx264 --extra-cflags="-Ix264/" --extra-ldflags="-ldl -Lx264/"
cd ..
Modify mkvserver/Makefile
LAV_LDFLAGS = -L ${FFMPEG}/libavcodec \
-L ${FFMPEG}/libavformat \
-L ${FFMPEG}/libavutil \
-L ${FFMPEG}/libswresample \
-L ${FFMPEG}/x264 \
-lavformat -l m \
-lavcodec -pthread -lm -lx264 -pthread -lswresample \
-lavutil -pthread -lrt -lm \
-lx264 -lpthread -lm -ldl
Build mkvserver
cd mkvserver
cd ..
Transfer 'server' to raspberry pi, name it mkvserver and place it in /usr/bin

Configuring and Launching

Useful Commands

udevadm info -n /dev/video0
arecord -L / arecord -l
vcgencmd get_camera
ffmpeg -hide_banner -f v4l2 -list_formats all -i /dev/video0
v4l2-ctl --all

Installing and Configuring Raspberry Pi


1. Download

Download Image from

2. Write Image

Plug memory card into a Linux PC

# Identify id of card which has just been plugged in

# Copy the image onto the card
dd bs=4M if=<imagefile.img> of=/dev/sd<x>

Configuring (via HDMI)


Connect Pi to HDMI screen, and connect USB keyboard
Plug card into Pi, and turn on

Logging In and Enabling ssh

# Login with user/password as pi/raspberry

# Enable SSH (interfacing options, select Yes to SSH)
sudo raspi-config

# Reboot Pi
sudo reboot

Enabling Wireless

sudo raspi-config

Configuring (Headless)

Enabling SSH

# Remove and re-insert card into the Linux PC
# The drive should auto-mount

# Create an 'ssh enable' file
touch /mount/<user>/boot/ssh

Enabling Wireless

# Create a wireless configuration file
cat > /mount/<user>/boot/wpa_supplicant.conf 

country=GB ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev update_config=1 network={ ssid="your_real_wifi_ssid" scan_ssid=1 psk="your_real_password" key_mgmt=WPA-PSK }


sudo pri-update


Raspberry Pi IR

Notes to make IR shield (made by LinkSprite) work in Raspberry Pi 3 (bought from Amazon [1]).

The vendor has some documentation [2] but that is not complete and sufficient for Raspbian Stretch.
Following are the changes that I made to make it work.

$ sudo apt-get update
$ sudo apt-get install lirc

# Add the following lines to /etc/modules file
lirc_rpi gpio_in_pin=18 gpio_out_pin=17

# Add the following lines to /etc/lirc/hardware.conf file
LIRCD_ARGS="--uinput --listen"

# Update the following line in /boot/config.txt (incomment if required)

# Update the following lines in /etc/lirc/lirc_options.conf
# Update the following lines in /etc/lirc/lircd.conf
driver    = default
device    = /dev/lirc0

# Reboot before testing
$ reboot

$ sudo /etc/init.d/lirc stop
$ sudo /etc/init.d/lirc start

# Check status to make lirc is running
$ sudo /etc/init.d/lirc status

# Populate lircd.conf

# this config file was automatically generated
# using lirc-0.8.6(default) on Fri Sep 10 22:02:46 2010
# contributed by
# brand:                       TV LG 42"LD420
# model no. of remote control: AKB72915207
# devices being controlled by this remote:

begin remote

  name  LG_AKB72915207
  bits           16
  eps            30
  aeps          100

  header       9056  4448
  one           601  1647
  zero          601   538
  ptrail        601
  repeat       9081  2199
  pre_data_bits   16
  pre_data       0x20DF
  gap          108229
  toggle_bit_mask 0x0

      begin codes
          KEY_POWER                0x10EF                    #  Was: power
          energy                   0xA956
          avmode                   0x0CF3
          input                    0xD02F
          tvrad                    0x0FF0
          KEY_1                    0x8877                    #  Was: 1
          KEY_2                    0x48B7                    #  Was: 2
          KEY_3                    0xC837                    #  Was: 3
          KEY_4                    0x28D7                    #  Was: 4
          KEY_5                    0xA857                    #  Was: 5
          KEY_6                    0x6897                    #  Was: 6
          KEY_7                    0xE817                    #  Was: 7
          KEY_8                    0x18E7                    #  Was: 8
          KEY_9                    0x9867                    #  Was: 9
          KEY_0                    0x08F7                    #  Was: 0
          KEY_LIST                 0xCA35                    #  Was: list
          q.view                   0x58A7
          KEY_VOLUMEUP             0x40BF                    #  Was: vol_up
          KEY_VOLUMEDOWN           0xC03F                    #  Was: vol_down
          KEY_CHANNELUP            0x00FF                    #  Was: ch_up
          KEY_CHANNELDOWN          0x807F                    #  Was: ch_down
          KEY_FAVORITES            0x7887                    #  Was: fav
          ratio                    0x9E61
          KEY_MUTE                 0x906F                    #  Was: mute
          KEY_MENU                 0xC23D                    #  Was: menu
          KEY_INFO                 0xD52A                    #  Was: guide
          KEY_UP                   0x02FD                    #  Was: up
          KEY_DOWN                 0x827D                    #  Was: down
          KEY_LEFT                 0xE01F                    #  Was: left
          KEY_RIGHT                0x609F                    #  Was: right
          KEY_OK                   0x22DD                    #  Was: ok
          KEY_BACK                 0x14EB                    #  Was: back
          KEY_INFO                 0x55AA                    #  Was: info
          KEY_EXIT                 0xDA25                    #  Was: exit
          KEY_RED                  0x4EB1                    #  Was: red
          KEY_GREEN                0x8E71                    #  Was: green
          ellow                    0xC639
          KEY_BLUE                 0x8679                    #  Was: blue
          exit2                    0x04FB
          t.opt                    0x847B
          KEY_SUBTITLE             0x9C63                    #  Was: subtitle
          KEY_STOP                 0x8D72                    #  Was: stop
          KEY_PLAY                 0x0DF2                    #  Was: play
          KEY_PAUSE                0x5DA2                    #  Was: pause
          KEY_REWIND               0xF10E                    #  Was: <<
          KEY_FORWARD              0x718E                    #  Was: >>
          simplink                 0x7E81
      end codes

end remote

# To test if lirc output driver is working
$ irsend SEND_ONCE LG_AKB72915207 KEY_POWER

# To test if lirc input driver is working
$ sudo /etc/init.d/lircd stop
$ mode2 -d /dev/lirc0
<press a key in remote and you should see multple lines like below>
pulse 560
space 1706
pulse 535

# to record a custom remote/register a remote device
$ sudo /etc/init.d/lircd stop
$ sudo irrecord -d /dev/lirc0 ~/lircd.conf
# follow the instruction prompted by the above command carefully
# at the end ~/lircd.conf file will be generated

# backup the original lircd.conf
$ sudo mv /etc/lirc/lircd.conf /etc/lirc/lircd_original.conf
$ sudo cp ~/lircd.conf /etc/lirc/lircd.conf
$ sudo /etc/init.d/lircd start

# you can test if the recorded remote works by
$ irsend SEND_ONCE <device-name> KEY_POWER
$ irsend SEND_ONCE <device-name> KEY_VOLUMEUP


Wednesday, 3 June 2020

Method For Calculating a 3D Printer Maximum Flow Rate


This note describes the steps taken to test and measure the maximum filament flow rate supported by a 3D printer.

The flow rate depends on a number of factors, including:

  • Hot end heating capability: how quickly can the hot end get heat into the filament as it passes through.
  •  Filament and hot-end differential temperature: How much energy is taken from the hot end when the filament is melted.
  •  Drive capability of the extruder: How quickly can the extruder motor pass filament into the hot end.

Test Overview

The test passes different lengths of filament through the hot end at a set temperature over a fixed 10 second interval.

It is noted when the extruder starts to click / slip, and the extruded filament is weighed and compared against the expected results.


Download the document here: Method for Calculating a 3D Printer Maximum Flow Rate