In a previous blog entry, I explained (in French) that I added Octoprint to my Dagoma DiscoEasy200 thanks to an Orange Pi Zero.

The best guide I found is the one from deloarts.

orange-pi-zero

Remark: when I wrote this article, I discovered that new editions of the Orange Pi Zero exists (Plus / Plus2 H3, H5...). I'm using the basic Orange Pi Zero with 512Mo RAM

Webcam module

I recently dismantled an old Android 2.2 notebook before throwing it away (based on the Wondermedia WM8650). I found a little module with a camera on it, and I asked myself if it could be reused.

IMG_20180512_202126

The chip on the module is an Etron eSP268.

etron-esp268

And 4 wires are connected to the module (red / black / blue / white).
It seems that the module is just connected through an USB interface !
I gave it a shot :

  • Red: 5V
  • Black: GND
  • White: Data positive
  • Blue: Data negative

IMG_20180512_202247

And it works! No driver to install to get it work with Windows 10.
The webcam is an UVC compatible device, which is a good news as it supported by Linux.

Connect the webcam to the Orange Pi Zero

Hardware

As the only USB port socket on the Orange PI Zero is used by the 3D printer, I looked at the Orange PI Zero pinout:

Orange-Pi-Zero-Pinout
Source

We can see that 2 USB port pins are available (USB-Dx2 / USB-Dx3).
I chose to use the USB-DM2 / USB-DP2 as they are close to 5V and GND pins.

I removed the micro USB breakout board and put some pin headers:

IMG_20180512_205008

IMG_20180512_205513

Software

I'm using the following OS:

ARMBIAN 5.38 stable Ubuntu 16.04.4 LTS 4.14.18-sunxi

I found some useful informations on the Sunxi website.

Once that the OS booted, I tried to see if the webcam was recognized:

root@octoprint:/dev# ls -ltrh /dev/video*
ls: cannot access '/dev/video*': No such file or directory

So I checked the USB devices:

root@octoprint:/dev# lsusb
Bus 008 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 005 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 006 Device 002: ID 0403:6001 Future Technology Devices International, Ltd FT232 USB-Serial (UART) IC
Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

To discover the webcam informations, I had to install hwinfo

root@octoprint:/dev# apt get install hwinfo
root@octoprint:/dev# hwinfo --usb
13: USB 00.1: 0000 Unclassified device
  [Created at usb.122]
  Unique ID: sjcF.B8XmjCc9XQ2
  Parent ID: zPk0.J9mAFna3wT7
  SysFS ID: /devices/platform/soc/1c1c000.usb/usb4/4-1/4-1:1.1
  SysFS BusID: 4-1:1.1
  Hardware Class: unknown
  Model: "Cubeternet WebCam"
  Hotplug: USB
  Vendor: usb 0x1e4e "Cubeternet"
  Device: usb 0x0100 "WebCam"
  Revision: "12.18"
  Driver: "uvcvideo"
  Driver Modules: "uvcvideo"
  Speed: 480 Mbps
  Module Alias: "usb:v1E4Ep0100d1218dcEFdsc02dp01ic0Eisc02ip00in01"
  Config Status: cfg=new, avail=yes, need=no, active=unknown
  Attached to: #16 (Hub)

I checked on the UVC Linux driver website, and it should be supported:

1e4e:0100 / USB 2.0 Camera / Etron Technologies

Linux-UVC-driver---tools

After looking around on the web to get it working, I understood that I just had to enable the kernel module:

root@octoprint:/dev# modprobe uvcvideo

root@octoprint:/dev# ls -ltrh /dev/video*
crw-rw---- 1 root video 81, 0 May 12 19:17 /dev/video0

root@octoprint:/dev# lsusb
Bus 008 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 005 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 002: ID 1e4e:0100 Cubeternet WebCam
Bus 004 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 006 Device 002: ID 0403:6001 Future Technology Devices International, Ltd FT232 USB-Serial (UART) IC
Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Installed and used some tools to see the capacity of the webcam.

root@octoprint:/# apt install v4l-utils
root@octoprint:/# v4l2-ctl --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
        Index       : 0
        Type        : Video Capture
        Pixel Format: 'YUYV'
        Name        : YUYV 4:2:2
                Size: Discrete 640x480
                        Interval: Discrete 0.033s (30.000 fps)
                Size: Discrete 352x288
                        Interval: Discrete 0.033s (30.000 fps)
                Size: Discrete 320x240
                        Interval: Discrete 0.033s (30.000 fps)
                Size: Discrete 176x144
                        Interval: Discrete 0.033s (30.000 fps)
                Size: Discrete 160x120
                        Interval: Discrete 0.033s (30.000 fps)

So the webcam can be used at 30 fps with the 640x480 resolution. Enough for a free module.

Use the webcam with Octoprint

To be able to use the webcam with Octoprint, the webcam stream must be exposed over HTTP.
To do that, Octoprint website advise to use mjpg-streamer.

Webcam stream with "mjpg-streamer"

octoprint@octoprint:/home/octoprint$ apt-get install cmake libjpeg8-dev
octoprint@octoprint:/home/octoprint$ git clone https://github.com/jacksonliam/mjpg-streamer.git
octoprint@octoprint:/home/octoprint/mjpg-streamer/mjpg-streamer-experimental$ make

Please note that I installed the tool (make install) but I think that it's not mandatory.

root@octoprint:/home/octoprint/mjpg-streamer/mjpg-streamer-experimental# make install

Now, it's time to test the stream:

root@octoprint:/# mjpg_streamer -i "input_uvc.so -r 640x480 -f 30" -o "output_http.so"
MJPG Streamer Version: git rev: 821c330ea6bbb5fbed98d48e00aac156e923161b
 i: Using V4L2 device.: /dev/video0
 i: Desired Resolution: 640 x 480
 i: Frames Per Second.: 30
 i: Format............: JPEG
 i: TV-Norm...........: DEFAULT
 i: Could not obtain the requested pixelformat: MJPG , driver gave us: YUYV
    ... will try to handle this by checking against supported formats.
    ... Falling back to YUV mode (consider using -yuv option). Note that this requires much more CPU power
UVCIOC_CTRL_ADD - Error at Pan (relative): Inappropriate ioctl for device (25)
UVCIOC_CTRL_ADD - Error at Tilt (relative): Inappropriate ioctl for device (25)
UVCIOC_CTRL_ADD - Error at Pan Reset: Inappropriate ioctl for device (25)
UVCIOC_CTRL_ADD - Error at Tilt Reset: Inappropriate ioctl for device (25)
UVCIOC_CTRL_ADD - Error at Pan/tilt Reset: Inappropriate ioctl for device (25)
UVCIOC_CTRL_ADD - Error at Focus (absolute): Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at Pan (relative): Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at Tilt (relative): Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at Pan Reset: Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at Tilt Reset: Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at Pan/tilt Reset: Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at Focus (absolute): Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at LED1 Mode: Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at LED1 Frequency: Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at Disable video processing: Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at Raw bits per pixel: Inappropriate ioctl for device (25)
 o: www-folder-path......: disabled
 o: HTTP TCP port........: 8080
 o: HTTP Listen Address..: (null)
 o: username:password....: disabled
 o: commands.............: enabled

Sadly, this webcam cannot output MJPG, which force the streamer to transcode the stream, and use a lot of CPU power (30% of the CPU of my Orange PI).

mjpg_streamer_cpu

The stream is now available!

http://192.168.0.100:8080/?action=stream
(of course, you have to change the IP of my device by yours...)

Before configuring Octoprint, I had to install ffmpeg:

root@octoprint:/# apt-get install ffmpeg

Scripts to be able to start / stop the webcam

As the streamer uses a lot of CPU, I want to be able to start it / stop it directly from Octoprint.

I adapted the scripts that are available on GitHub for my configuration.

webcam.sh

octoprint@octoprint:~$ mkdir scripts
octoprint@octoprint:~$ cd scripts/
octoprint@octoprint:~/scripts$ vim webcam.sh
#!/bin/bash
# Start / stop streamer daemon

case "$1" in
    start)
        /home/octoprint/scripts/webcamDaemon.sh >/dev/null 2>&1 &
        echo "$0: started"
        ;;
    stop)
        pkill -x webcamDaemon
        pkill -x mjpg_streamer
        echo "$0: stopped"
        ;;
    *)
        echo "Usage: $0 {start|stop}" >&2
        ;;
esac
octoprint@octoprint:~/scripts$ chmod a+x webcam.sh

webcamDaemon.sh

octoprint@octoprint:~/scripts$ vim webcamDaemon.sh
#!/bin/bash

MJPGSTREAMER_HOME=/home/octoprint/mjpg-streamer/mjpg-streamer-experimental
MJPGSTREAMER_INPUT_USB="input_uvc.so"

# init configuration
camera="auto"
camera_usb_options="-r 640x480 -f 30"

if [ -e "/boot/octopi.txt" ]; then
    source "/boot/octopi.txt"
fi

# runs MJPG Streamer, using the provided input plugin + configuration
function runMjpgStreamer {
    input=$1
    pushd $MJPGSTREAMER_HOME
    echo Running ./mjpg_streamer -o "output_http.so -w ./www" -i "$input"
    LD_LIBRARY_PATH=. ./mjpg_streamer -o "output_http.so -w ./www" -i "$input"
    popd
}


# starts up the USB webcam
function startUsb {
    logger "Starting USB webcam"
    runMjpgStreamer "$MJPGSTREAMER_INPUT_USB $camera_usb_options"
}

# echo configuration
echo camera: $camera
echo usb options: $camera_usb_options

# keep mjpg streamer running if some camera is attached
while true; do
    if [ -e "/dev/video0" ] && { [ "$camera" = "auto" ] || [ "$camera" = "usb" ] ; }; then
        startUsb
    elif [ "`vcgencmd get_camera`" = "supported=1 detected=1" ] && { [ "$camera" = "auto" ] || [ "$camera" = "raspi" ] ; }; then
        logger "Not supported"
    fi

    sleep 120
done
octoprint@octoprint:~/scripts$ chmod a+x webcamDaemon.sh

Edit Octoprint configuration

octoprint@octoprint:~/scripts$ vim ~/.octoprint/config.yaml

I had to add the system section:

system:
  actions:
  - action: streamon
    command: /home/octoprint/scripts/webcam.sh start
    confirm: false
    name: Start video stream
  - action: streamoff
    command: /home/octoprint/scripts/webcam.sh stop
    confirm: false
    name: Stop video stream

Octoprint user rights

Currently the octoprint user doesn't have the right to use the video devices. When I ran the script with this user, I got an error:

octoprint@octoprint:~/scripts$ ./webcamDaemon.sh
camera: auto
usb options: -r 640x480 -f 30
~/mjpg-streamer/mjpg-streamer-experimental ~/scripts
Running ./mjpg_streamer -o output_http.so -w ./www -i input_uvc.so -r 640x480 -f 30
MJPG Streamer Version: git rev: 821c330ea6bbb5fbed98d48e00aac156e923161b
 i: Using V4L2 device.: /dev/video0
 i: Desired Resolution: 640 x 480
 i: Frames Per Second.: 30
 i: Format............: JPEG
 i: TV-Norm...........: DEFAULT
ERROR opening V4L interface: Permission denied
 Init v4L2 failed !! exit fatal
 i: init_VideoIn failed
~/scripts
ls -l /dev/video0

So I add the user to the video group:

root@octoprint:/home/octoprint# vim /etc/group

By editing this line:

video:x:44:jmd,octoprint

Then, I restarted Octoprint:

octoprint@octoprint:~/scripts$ sudo service octoprint restart

Octoprint configuration

It's now time to changes the setting of Octoprint:

octoprint_settings

Don't forget to flush the cache of your browser to see the changes in Octoprint.

Now, in the "Control" tab, an area can display the webcam stream. To enable the stream, one new item is also available in the toolbar.

octoprint-stream-control

And...

octoprint-webcam-result

I now have to find the best way to fix the webcam.
The quality is not good, but it is enough to check the printer status remotely.

If you want to open your octoprint on Internet, there is few steps left. But personally, for security reasons, I only check my octoprint through a VPN connection to my home network.