Coding Chase - Projects

My 3D Hub

Thank You For Donating:

Ikeeki (linux-sunxi@irc.freenode.net)
Computer Troubleshooters Brasil

Wednesday 30 December 2015

IoT Projects - ESP8266 [CTC-3D Printer Upgrade] ||

So, after having an ESP8266-01 control my CTC-3D printer LED lighting and Fan cooling, I decided to improve the solution further.

Moving more to ABS than PLA on prints, the fans stopped being that necessary - but what stood out as being a lot more interesting would be to actually turning the printer on or off.

Using the same principles as before, I replaced the Fan part of the solution and added the printer power cord to the available relay.

As an extra, I left cubietruck to manage Octoprint and the remaining solutions in previous posts and set out to build a nice embedded cluster:

  • 4 boards (even cubieboard A10 boards will do for this, but one might consider a cheaper alternative as the Orange Pi perhaps);
  • 4 webcams, in my case, the Hercules Twist HD as it molds perfectly to the case;
  • placing each webcam on the top corners of the printer case, pointing to the heat bed;
  •  Using cubietruck as the manager of the video solution and controlling each of the 4 boards as video feeds;

And since using the command line to issue MQTT commands wasn't actually that practical, I started working on a web platform to manage the solution.

I spent some time working with MEAN.js which I found to be brilliant by the way, integrated MQTT.js and socket.io into the base boilerplate as well as the live video feeds from the webcams.

In the end I got exactly what I wanted:

  • the ESP8266-01 connects to CloudMQTT, a cloud-based, free MQTT broker (moved to it after everything was confirmed to be working properly using mosquitto locally);
  • the MQTT broker is accessible by the MEAN.js web app (which later got published to heroku);
  • the web app uses MQTT.js to subscribe to CloudMQTT and socket.io to perform realtime UI updating if necessary (if I decide to use sensors in the future);
  • the webcams stream the video to the web app.
Using the app, either desktop or tablet or mobile, I'm able to work it:
  1. turn the printer on/off, which saves some power;
  2. turn the lighting on/off, in case there's poor lighting in the room;
  3. use a slicer remotely, like slic3r, generate gcode and upload it to Octoprint;
  4. run the prints remotely and accompany the status using the webcams.
 Some screenshots from the development phase, the web app is very crude, just the buttons and the video streams, just one stream being replicated at the time.

In spite of travelling over the web, the response time with MQTT is lightning fast, basically feels as if a local physical switch is being used...!



 
 As an alternative to MEANjs, there's also meteor.js but I haven't actually looked into that one, apparently it would have saved me some time integrating MQTT an socket.io - perhaps on my next project!
 

CTC-3D and Sitall

I've been rather busy lately but thought I'd document a few relevant pointers regarding 3D printing in general and my CTC-3D printer in particular.

First off, documenting my Octoprint settings for the CTC-3D (at least the relevant bits):










Also, while using the stock firmware + octoprint, I was using ReplicatorG as my slicer software.

After upgrading the firmware, I also moved to Slic3r. ReplicatorG is quite old and not being maintained anymore, apart from the Sailfish variant I guess - whereas Slic3r has many more options and also the possibility of exporting configs, which means I can easily use it on another machine to generate the gcode without having to set it up all over again.

Using slic3r, I just had to make sure to select Makerbot (sailfish) flavor gcode in the settings once I changed firmware.

Second, the fact that after being successful in printing with PLA and ABS using just painter tape, I decided to test printing on glass.

I decided to go with Sitall Glass since the Ebay supplier claimed it can be used without any other adherent substances like ABS goo, glue stick, painter tape, etc. - as a reference, this is seller.

Testing primarily with ABS, I found that the prints would detach from the glass plate mid-print and went on to investigate.

Other than that, the glass seems like it will do the job nicely, it is easily washable and as opposed to the painter tape, the prints won't get line marks on the bottom surface, where the tape strips meet on the plate.

I got myself an infrared thermometer, based on the youtube video below, which was very helpful


What I found out is that, as with in the video, the actual thermistor (thermal sensor) readings on the plate differ significantly from the measurements with the thermometer.

Isolating the printer case side/front panels didn't get it to 110ºC as required by the glass, as I also found out that the stock thermistor underneath the heat bed won't allow such temperatures. Also, the CTC-3D stock firmware is limited to 120ºC max.

After some investigating, two possible solutions were found:

  1. upgrade from stock firmware to sailfish firmware in order to be able to set higher heatbed temperatures, thus increasing the real bed temperature as well, and closer to 110ºC
  2. replace the heatbed thermistor sensor by another one, in order to reduce the temp difference between the one being measured and the actual temp on the bed.

I then set out to replacing the thermistor, based on a 3DHubs user advice as well as upgrade the stock firmware to the Sailfish firmware, in order to be able to set higher heatbed temperatures.

Upgrading the stock firmware wasn't without its hiccups, but no big deal:

[revised from my own post on 3DHubs]

I've recently upgraded my CTC to Sailfish 7.7 (r1432) - I followed the [sailfish firmware install] tutorial, used replicatorg-0040r33-Sailfish-linux.tgz from the thingiverse link as I'm using linux and it worked ok.

A member [on 3DHubs] helped me locate the reset button - it is a hole near the USB port in the back of the printer.

To upgrade the firmware, under linux 64bit, I had to install libusb-0.1-4 : i386 because RepG was reporting errors in the console regarding this lib not being found.

Once RepG was ok, doing the firmware update was as follows in my case:

Used RepG to scan serial devices and got /dev/ttyACM0 detected (the printer)

Machine > Machine Type (Driver) > The Replicator Dual (Sailfish)
Then Upload New Firmware > Makerbot Replicator 1 Single & Dual (v1.5) > Sailfish 7.7 (r1432)


/home/wickwire/Downloads/replicatorg-0040r33-Sailfish/tools/avrdude -C/home/wickwire/Downloads/replicatorg-0040r33-Sailfish/tools/avrdude.conf -cstk500v1 -P/dev/ttyACM0 -b57600 -D -Uflash:w:/home/wickwire/.replicatorg/firmware/mighty_one-Sailfish-v7.7.0-r1432.hex:i -pm1280
avrdude: stk500_recv(): programmer is not responding


As RepG does a few retries before it timed out again in the log, I just pressed the reset button with a pen tip and it started flashing.

I was done in a few seconds (the terminal reported flashing success) - powered down, powered up and the LCD on the printer was working. Going through the options on the LCD to printer info I got the Sailfish info.

Did a factory reset using the printer LCD screen options, rebooted the printer, then checked the printer nozzle offsets and stuff as the guide mentions and all was ok, didn't change anything.

Printed a sample part as follow up using slic3r and being careful to update it to use makerbot (sailfish) instead of makerbot(makerware) and it worked properly.

At this point, the firmware upgrade was OK and printing with ABS on the Sitall glass works, provided I use hairspray for strong adhesion.

The infrared thermometer still registered a 95ºC max temperature on the glass, as I'm still to replace the thermistor.

Removing the heatbed was easy enough and this is what it looks like underneath:



The thermistor is highlighted in green on the photo. To replace it, I was advised to use a 100k ntc, so based on what I was looking at, I went with this model from Ebay (there are several available, mostly for Prusa and RepRap printers, but those are slightly different than what is used on this heatbed).


I'll update the blog with my findings once these parts are delivered.

Sunday 12 July 2015

IoT Projects - ESP8266 [CTC-3D Printer Upgrade]

Based on the previous blog posts on MQTT, ESP8266-01 and NodeMCU, I decided as mentioned before to upgrade my newly acquired 3D printer, a CTC-3D dual extruder printer.

The printer is awesome and while it already operates remotely via Octoprint on Cubietruck (see previous posts), I did find it useful to add a cooling system to it as well as some lighting inside the chassis, both to be remotely controlled as well.

This post is all about the lua scripts loaded to the ESP8266-01 wifi module, in order to achieve this.

First off, I had several issues with memory usage while using a stock nodeMCU firmware, meaning, a build containing all the available modules.

Trimming the fat from the firmware proved quite valuable in memory terms (check previous posts).

Then, moving on to the lua scripts, I managed to devise a basic management system where I can now update the wifi module configurations for WiFi and MQTT broker over the air, using the MQTT messaging system.

config_wifi.lua:

wifi_ssid='wifiHotspot'
wifi_pass='w1f1P4ss'

config_mqtt.lua:

mqtt_host='192.168.1.2'
mqtt_port=1883
mqtt_topic='topic-'..node.chipid() 
 
bootup.lua:
 
function bootup()
    wifi.setmode(wifi.STATION)
    wifi.sta.config(wifi_ssid,wifi_pass)
end




mqtt_connect.lua:


function mqttActivate()
            m:connect(mqtt_host, mqtt_port, 0, function(conn)
                print("connected to mqtt broker!")
                m:subscribe("/"..mqtt_topic,0, function(conn)
                 tmr.stop(3)
                 tmr.stop(2)
                end)
            end)
end

function mqttConnect()
  m = mqtt.Client(wifi.sta.getmac(), 120, "user", "password")
  m:lwt("/lwt", wifi.sta.getmac(), 0, 0)

  m:on("offline", function(con)
       tmr.alarm(2, 10000, 1, function()
        print ("reconnecting to mqtt broker...")
        mqttActivate()
       end)
  end)

  tmr.alarm(3, 10000, 1, function()
        print("connecting to mqtt broker...")
   mqttActivate()
  end)

  mqttParse()

end

mqtt_parse.lua:


function mqttParse()
  m:on("message", function(conn, topic, data)
    if data ~= nil then
      local i=1
      local offset=0
      while string.find(data,";") do

       field = string.sub(data, offset, string.find(data,":")-1)
       dataArray[field] = string.sub(data, string.find(data,":")+1, string.find(data,";")-1)
       data = string.sub(data, string.find(data, ";") + 1, string.len(data))

       i = i + 1
      tmr.wdclr()
      end

      if dataArray['type'] == 'config-update' then 
       confUpdate()
      elseif dataArray['type'] == 'gpio-control' then
       gpioControl()
      end
    end
  end)
end
 
config_update.lua:

function confUpdate()
 print('changing configuration for module: '..dataArray['setting'])

 if dataArray['setting'] == 'wifi' then
  file.open("config_wifi.lua", "w+")
  file.writeline('wifi_ssid=\''..dataArray['ssid']..'\'')
  file.writeline('wifi_pass=\''..dataArray['pass']..'\'')
  file.close()
 elseif dataArray['setting'] == 'mqtt' then
  file.open("config_mqtt.lua", "w+")
  file.writeline('mqtt_host=\''..dataArray['host']..'\'')
  file.writeline('mqtt_port='..dataArray['port'])
  file.writeline('mqtt_topic=\'topic-'..node.chipid()..'\'')
  file.close()
 end

 node.restart()

end

gpio_control.lua:


function gpioControl()
 print('setting GPIO pin: '..dataArray['gpio'])
 
 pin=0
 
 if dataArray['gpio'] == '0' then
  pin=3
 elseif dataArray['gpio'] == '2' then
  pin=4
 end

 if dataArray['state'] == 'on' then
  gpio.write(pin, gpio.HIGH)
 elseif dataArray['state'] == 'off' then
  gpio.mode(pin, gpio.INPUT)
 end

end

init.lua: 
 
require 'config_wifi'
require 'config_mqtt'
require 'bootup'
require 'mqtt_connect'
require 'mqtt_parse'
require 'config_update'
require 'gpio_control'

dataArray={}

bootup()

gpio.mode(3, gpio.INPUT)
gpio.mode(4, gpio.INPUT)

mqttConnect()

 
The WiFi module will try to connect the the WiFi network and from there, to the
MQTT broker. Once connected, it will register to a new topic based on its ID,
which you'll be able to catch in the MQTT broker log file.
 
You'll want to compile all scripts, except for config_wifi.lua, config_mqtt.lua
and init.lua.

I'm still learning Lua, hadn't used it before, which is to say that there's
definitely room for improvement here - however, as they stand, these
scripts do the job in allowing for remote, on demand control!
 
And finally, at this point, you'll be able to publish messages
to your MQTT broker server in order to operate your wifi module:

mosquitto_pub -h 192.168.1.2 -p 1883 -t /topic-12345678 -m 'type:gpio-control;gpio:0;state:on;'
mosquitto_pub -h 192.168.1.2 -p 1883 -t /topic-12345678 -m 'type:gpio-control;gpio:0;state:off;'
mosquitto_pub -h 192.168.1.2 -p 1883 -t /topic-12345678 -m 'type:gpio-control;gpio:2;state:on;'
mosquitto_pub -h 192.168.1.2 -p 1883 -t /topic-12345678 -m 'type:gpio-control;gpio:2;state:off;'

mosquitto_pub -h 192.168.1.2 -p 1883 -t /topic-12345678 -m 'type:config-update;setting:mqtt;host:192.168.1.3;port:1883;'
mosquitto_pub -h 192.168.1.2 -p 1883 -t /topic-12345678 -m 'type:config-update;setting:wifi;ssid:wifiHotspot;pass:w1f1P4ss;'

IoT Projects - ESP8266 [programming]

Now all this is left is to program the ESP8266-01 module...!



For this part, I used one of these:

FT232RL 3.3V 5V FTDI USB to TTL Serial Adapter Module for Arduino Mini Port IDXX

Flashing the NodeMCU firmware

1) connect GPIO0 -> GND (Only for when loading the firmware because this pin is what defines the boot mode: firmware load mode or regular mode)

2) git clone https://github.com/themadinventor/esptool.git

3) get your firmware, either from github, the online custom build website from my previous post, etc.

4) sudo python esptool.py --port /dev/ttyUSB0 --baud 115200 write_flash 0x00000 /opt/ESP8266/nodemcu.firmwares/nodemcu_latest.bin

Connecting...
Erasing flash...
Writing at 0x00062000... (100 %)

Leaving...

Writing and Loading Some LUA Scripts

1) remember to disconnect GPIO0 from GND

2) git clone https://github.com/kmpm/nodemcu-uploader.git 

3) sudo ./nodemcu-uploader.py -p /dev/ttyUSB0 -b 115200 upload ../lua.scripts/webserver.lua:webserver.lua [--compile] [--restart]
 
Changing communication to 115200 baud
Preparing esp for transfer.
Transfering webserver.lua as webserver.lua
All done!
 
Using the parameter --compile will trigger lua script compiling at the wifi module:
after uploading the original lua script to the module, the python script will issue
the compile command, generating an lc binary file and deleting the original lua file
on the module.

Using the --restart parameter will issue a module reboot after uploading the script.

IoT Projects - ESP8266 [wiring]

My apologies in advance if the diagram below isn't all that proper, as mentioned before, I'm a bit of a newbie when it comes to wiring circuits...!

Anyways, the important bits to grasp here are:

1) the ESP will handle 3.3v max - going beyond that will most likely damage it
- using a 3.3v voltage regulator to ensure that the voltage being delivered to it is correct

2) the LED strip is represented by the LED on the upper part of the diagram
3) the case fans are represented by the LEDs on the lower part of the diagram
4) a couple of relays are required for wiring the fans and LED strip - and those are 5v relays, so another 5v voltage regulator is required
5) the case fans run at 12v
6) a single power supply is being used: 12v/1A
7) the wifi module's purpose is to control the relays using its two available GPIO pins, by processing MQTT messages from the broker (see previous posts on MQTT and Cubietruck)






Parts list follows:

IKEA Dioder LED strips
5V voltage regulators
3.3V voltage regulators
12V 1.0A Power Supply
5V Relay Module Board Shield
120mm Quiet Case Fans


IoT Projects - ESP8266



The ESP8266-01 Wifi Module is a really cheap component which is programmable and includes two GPIO pins (although it seems you can use the TX/RX pins as GPIO as well and even expand available GPIOs by soldering a few extra pins to the chip legs).

There is quite a community around this module, there are several variants of it - and so far I've been quite impressed by the wifi range on this, as well as the size and features.

First off, there's the official espressif SDK and github resources:

http://espressif.com/new-sdk-release/
https://github.com/esp8266
https://github.com/esp8266/at-command-set


... and then there's NodeMCU:

http://nodemcu.com/index_en.html
https://github.com/nodemcu/nodemcu-firmware
http://www.nodemcu.com/docs/

NodeMCU relies on a Lua interpreter for the applicational part, which makes it easier to code but on the other hand, may require more tweaking with regards to memory usage.

There are however some valuable tricks going with NodeMCU, which was the method I ended up going with on my experiments:

1) lua scripts can be compiled to bytecode files .lua > .lc
2) the NodeMCU firmware build can be customized to include only the modules you'll be needing:

http://frightanic.com/nodemcu-custom-build/

For my solution, I ended up choosing the dev-0.96 github branch and only 7 modules:

node / file / GPIO / WiFi / timer / UART / MQTT

Using the float version rather than integer also seemed to do more for me in terms of system stability.

As for the lua scripts inside the unit, I've managed to secure a couple of interesting features already:

1) MQTT broker reconnect after either wifi or broker outage/recovery
2) ESP settings for wifi and MQTT to be updated over the air (by sending config update messages over MQTT to the wifi module, updating its configuration and rebooting it)

It's equally possible to change timer durations or GPIO operation parameters over MQTT if required - and of course, receive data from the wifi module regarding its status!

IoT Projects - MQTT

As a starting point, I've been looking at a couple of message protocols in order to interact with my embedded devices.

One protocol in particular stood out - MQTT

Basically you'll need to set up a message server (or broker) which will then manage the message queues your clients will be using.

That in turn led me to Mosquitto. Installing Mosquitto on an Ubuntu machine is easy enough, just follow these steps and you're good to go.

Moving on to my embedded boards, my Cubietruck looked like it could handle it - already running Gitlab, Octoprint and a couple more, so why not?

I'm using Cubian, and unfortunately the repo available package for Mosquitto is too old (2012), so I had to install Mosquitto from source:

wget http://mosquitto.org/files/source/mosquitto-1.4.2.tar.gz
sudo apt-get install libc-ares-dev

sudo apt-get install uuid-dev

sudo useradd mosquitto
sudo mkdir /var/log/mosquitto
sudo chown mosquitto:root /var/log/mosquitto/


tar xvzpf mosquitto-1.4.2.tar.gz
cd mosquitto-1.4.2
make clean && make -j3
sudo make install



/etc/mosquitto/mosquitto.conf:


# Place your local configuration in /etc/mosquitto/conf.d/
#
# A full description of the configuration file is at
# /usr/share/doc/mosquitto/examples/mosquitto.conf.example

pid_file /var/run/mosquitto.pid

persistence true
persistence_location /var/lib/mosquitto/

log_dest file /var/log/mosquitto/mosquitto.log

 

/etc/init.d/mosquitto:

#! /bin/sh

### BEGIN INIT INFO
# Provides:        mosquitto
# Required-Start:    $remote_fs $syslog
# Required-Stop:    $remote_fs $syslog
# Default-Start:    2 3 4 5
# Default-Stop:        0 1 6
# Short-Description:    mosquitto MQTT v3.1 message broker
# Description:
#  This is a message broker that supports version 3.1 of the MQ Telemetry
#  Transport (MQTT) protocol.

#  MQTT provides a method of carrying out messaging using a publish/subscribe
#  model. It is lightweight, both in terms of bandwidth usage and ease of
#  implementation. This makes it particularly useful at the edge of the network
#  where a sensor or other simple device may be implemented using an arduino for
#  example.
### END INIT INFO

set -e

PIDFILE=/var/run/mosquitto.pid
DAEMON=/usr/local/sbin/mosquitto

# /etc/init.d/mosquitto: start and stop the mosquitto MQTT message broker

test -x ${DAEMON} || exit 0

umask 022

. /lib/lsb/init-functions

# Are we running from init?
run_by_init() {
    ([ "$previous" ] && [ "$runlevel" ]) || [ "$runlevel" = S ]
}

export PATH="${PATH:+$PATH:}/usr/sbin:/sbin:/usr/local/sbin"

case "$1" in
  start)
    if init_is_upstart; then
        exit 1
    fi
    log_daemon_msg "Starting network daemon:" "mosquitto"
    if start-stop-daemon --start --quiet --oknodo --background  --make-pidfile --pidfile ${PIDFILE} --exec ${DAEMON} -- -c /etc/mosquitto/mosquitto.conf ; then
        log_end_msg 0
    else
        log_end_msg 1
    fi
    ;;
  stop)
    if init_is_upstart; then
        exit 0
    fi
    log_daemon_msg "Stopping network daemon:" "mosquitto"
    if start-stop-daemon --stop --quiet --oknodo --pidfile ${PIDFILE}; then
        log_end_msg 0
        rm -f ${PIDFILE}
    else
        log_end_msg 1
    fi
    ;;


  reload|force-reload)
    if init_is_upstart; then
        exit 1
    fi
    log_daemon_msg "Reloading network daemon configuration:" "mosquitto"
        if start-stop-daemon --stop --signal HUP --quiet --oknodo --pidfile $PIDFILE; then
            log_end_msg 0
        else
            log_end_msg 1
        fi   
    ;;

  restart)
    if init_is_upstart; then
        exit 1
    fi
    log_daemon_msg "Restarting network daemon:" "mosquitto"
    if start-stop-daemon --stop --quiet --oknodo --retry 30 --pidfile ${PIDFILE}; then
        rm -f ${PIDFILE}
    fi
    if start-stop-daemon --start --quiet --oknodo --background --make-pidfile --pidfile ${PIDFILE} --exec ${DAEMON} -- -c /etc/mosquitto/mosquitto.conf ; then
        log_end_msg 0
    else
        log_end_msg 1
    fi
    ;;

  try-restart)
    if init_is_upstart; then
        exit 1
    fi
    log_daemon_msg "Restarting Mosquitto message broker" "mosquitto"
    set +e
    start-stop-daemon --stop --quiet --retry 30 --pidfile ${PIDFILE}
    RET="$?"
    set -e
    case $RET in
        0)
        # old daemon stopped
        rm -f ${PIDFILE}
        if start-stop-daemon --start --quiet --oknodo --background --make-pidfile --pidfile ${PIDFILE} --exec ${DAEMON} -- -c /etc/mosquitto/mosquitto.conf ; then
            log_end_msg 0
        else
            log_end_msg 1
        fi
        ;;
        1)
        # daemon not running
        log_progress_msg "(not running)"
        log_end_msg 0
        ;;
        *)
        # failed to stop
        log_progress_msg "(failed to stop)"
        log_end_msg 1
        ;;
    esac
    ;;

  status)
    if init_is_upstart; then
        exit 1
    fi
    status_of_proc -p ${PIDFILE} ${DAEMON} mosquitto && exit 0 || exit $?
    ;;

  *)
    log_action_msg "Usage: /etc/init.d/mosquitto {start|stop|reload|force-reload|restart|try-restart|status}"
    exit 1
esac

exit 0


cubie@Cubian:~$ sudo service mosquitto status
[FAIL] mosquitto is not running ... failed!
cubie@Cubian:~$ sudo service mosquitto start
[ ok ] Starting network daemon:: mosquitto.
cubie@Cubian:~$ sudo service mosquitto status
[ ok ] mosquitto is running.
cubie@Cubian:~$

Cubietruck, ESP8266 and a CTC 3D Printer

Lately I've been messing about with my new CTC 3D printer, but soon figured out that the whole 3D printing set up could do with some upgrades.

Before moving on to what is currently running in the office, I thought I'd break the subjects down a bit:

- Setting up LEDs and case fans on the printer chassis
- Figuring out a way to control them remotely

Since I'm already using a Cubietruck, I thought about using the GPIOs to control these external components. Still, that solution wouldn't be that different from what you can do with a Cubieboard, Cubietruck, Raspberry Pi and similar embedded boards, ranging from 40USD upwards.

So then I found out about the ESP8266-01 wifi module:



This tiny wifi module costs about 2USD (!!!) and while a lot of people consider it mainly as a cheap wifi upgrade for their arduino boards, it can do quite a bit on its own...!

I bought a few of these on Ebay recently, just curious about what I could actually do with them, so in the end, this little guy alone ended up controlling the LEDs and case fans on my 3D printer chassis.

But first off, an important disclaimer:

The electronics on this project was mostly picked up from tips and teachings from a couple of friends, more knowledgeable on the subject.

I'll be posting the several steps in this project on the blog, as soon as I'm able to clean up all the mess around the office...!

Sunday 21 June 2015

Cubietruck and a CTC Dual Extruder Printer - Part II

From the previous post, the CTC Dual Extruder is now connected to a Cubietruck running Octoprint, together with the GPX plugin.

At thingiverse you get all sorts of models, or things. Downloading the STL file and passing it on to the printer didn't work, so here's how I did it:

On my client PC I have ReplicatorG installed - I'm running Linux Mint and it installed properly on my laptop.

Loading the STL on ReplicatorG, you get to set up some basic variables such as extruder temperature and so on - and then you get the chance to generate a gcode file.

This is ideal, because Mark Walker's GPX plugin for Octoprint understands gcode and converts it to x3g for the printer!

So now I'm on my PC, there's a generated gcode file - all I have to do is upload it to Octoprint on Cubietruck using the WebUI and initiate the print job!

Print estimates, statistics and more are all visible on Octoprint - and going a step further, why not plug a USB Webcam to Cubietruck as well and stream all the action...? :)

I'll keep at this, hopefully with both extruders, different materials... let's see!

Cubietruck and a CTC Dual Extruder Printer - Part I

So, recently I bought a 3D printer - the CTC Dual Extruder. This device is actually a Makerbot Replicator 2 clone.

I've only had it for about 2 days, haven't changed firmwares or anything (it seems most experienced users recommend the Sailfish firmware) and for the time being, don't plan on messing with that.

And to be fair, the pre-installed firmware seems to be quite complete, so I'll keep it for as long as it suits my needs.

The printer has an SD card slot and a USB port. I started by using the SD card, but soon decided it would be preferable to move on to USB.

And what if you could WiFi it...?

Turns out, you can!

The CTC printer is USB connected to my Cubietruck and accessible over WiFi - or even from the internet, given the proper network configuration...!

To achieve this, I needed to set up octoprint on Cubietruck.


1) connecting the CTC dual extruder 3d printer to Cubietruck (Cubian)

cubie@Cubian:~$ sudo dmesg -c

connect the printer to cubietruck, on USB

cubie@Cubian:~$ dmesg

[  255.900873] ehci_irq: port change detect
[  255.905231] ehci_irq: port change detect
[  255.969149] ehci_irq: port change detect
[  256.206068] ehci_irq: port change detect
[  256.261515] The port change to OHCI now!
[  256.564307] usb 2-1: new full-speed USB device number 2 using sw-ohci
[  257.278351] cma: dma_alloc_from_contiguous(cma ef0ab1c0, count 1, align 0)
[  257.294415] cma: dma_alloc_from_contiguous(): returned d1078c80
[  257.300276] cma: dma_alloc_from_contiguous(cma ef0ab1c0, count 1, align 0)
[  257.314439] cma: dma_alloc_from_contiguous(): returned d1078ca0
[  257.320294] cma: dma_alloc_from_contiguous(cma ef0ab1c0, count 1, align 0)
[  257.334443] cma: dma_alloc_from_contiguous(): returned d1078cc0
[  257.340297] cma: dma_alloc_from_contiguous(cma ef0ab1c0, count 1, align 0)
[  257.364339] cma: dma_alloc_from_contiguous(): returned d1078ce0
[  257.370194] cma: dma_alloc_from_contiguous(cma ef0ab1c0, count 1, align 0)
[  257.384427] cma: dma_alloc_from_contiguous(): returned d1078e00
[  257.390279] cma: dma_alloc_from_contiguous(cma ef0ab1c0, count 1, align 0)
[  257.408925] cma: dma_alloc_from_contiguous(): returned d1078e20
[  257.424778] cma: dma_alloc_from_contiguous(cma ef0ab1c0, count 1, align 0)
[  257.430357] cma: dma_alloc_from_contiguous(): returned d1078e40
[  257.444711] cma: dma_alloc_from_contiguous(cma ef0ab1c0, count 1, align 0)
[  257.454701] cma: dma_alloc_from_contiguous(): returned d1078e60
[  257.460552] cma: dma_alloc_from_contiguous(cma ef0ab1c0, count 1, align 0)
[  257.484272] cma: dma_alloc_from_contiguous(): returned d1078e80
[  257.490176] cma: dma_alloc_from_contiguous(cma ef0ab1c0, count 1, align 0)
[  257.504485] cma: dma_alloc_from_contiguous(): returned d1078ea0
[  257.510341] cma: dma_alloc_from_contiguous(cma ef0ab1c0, count 1, align 0)
[  257.524444] cma: dma_alloc_from_contiguous(): returned d1078ec0
[  257.530302] cma: dma_alloc_from_contiguous(cma ef0ab1c0, count 1, align 0)
[  257.554409] cma: dma_alloc_from_contiguous(): returned d1078ee0
[  257.560397] cma: dma_alloc_from_contiguous(cma ef0ab1c0, count 1, align 0)
[  257.574399] cma: dma_alloc_from_contiguous(): returned d1078f00
[  257.580256] cma: dma_alloc_from_contiguous(cma ef0ab1c0, count 1, align 0)
[  257.604411] cma: dma_alloc_from_contiguous(): returned d1078f20
[  257.610266] cma: dma_alloc_from_contiguous(cma ef0ab1c0, count 1, align 0)
[  257.624412] cma: dma_alloc_from_contiguous(): returned d1078f40
[  257.630265] cma: dma_alloc_from_contiguous(cma ef0ab1c0, count 1, align 0)
[  257.654296] cma: dma_alloc_from_contiguous(): returned d1078f60
[  257.660154] cma: dma_alloc_from_contiguous(cma ef0ab1c0, count 1, align 0)
[  257.674425] cma: dma_alloc_from_contiguous(): returned d1078f80
[  257.680281] cma: dma_alloc_from_contiguous(cma ef0ab1c0, count 1, align 0)
[  257.708866] cma: dma_alloc_from_contiguous(): returned d1078fa0
[  257.713053] cdc_acm 2-1:1.0: ttyACM0: USB ACM device
[  257.721023] usbcore: registered new interface driver cdc_acm
[  257.728303] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters

2) cubietruck - install octoprint with GPX plugin



 sudo usermod -a -G tty cubie
 sudo usermod -a -G dialout cubie
 log out / log in

 cubie@Cubian:~$ groups
 cubie tty dialout sudo audio video gpio

 sudo apt-get install python-pip python-dev python-setuptools python-virtualenv   git libyaml-dev
 sudo apt-get clean

 cd
 mkdir ~/.octoprint

 git clone -b devel https://github.com/markwal/OctoPrint

 cd OctoPrint
 git rev-parse HEAD (mine is at commit
3857e7e0b04d7c72ab5d11df952fc21d61aa78ca)

 virtualenv --system-site-packages venv
 ./venv/bin/python setup.py install

 git clone https://github.com/markwal/OctoPrint-GPX
 cd OctoPrint-GPX
 git rev-parse HEAD (mine was at 64586f1e18188acbea0e22828a479c216cff287d)
 git submodule update --init
 ../venv/bin/python setup.py install
 cd

 ~/OctoPrint/venv/bin/octoprint

the output should show something like this:

(...)
2015-06-21 10:40:55,832 - octoprint.plugin.core - INFO - Found 6 plugin(s) providing 6 mixin implementations, 3 hook handlers
2015-06-21 10:40:55,852 - octoprint.plugin.core - INFO - Initialized 6 plugin(s)
2015-06-21 10:40:55,855 - octoprint.plugin.core - INFO - 6 plugin(s) registered with the system:
|  CuraEngine (bundled) = /home/cubie/OctoPrint/venv/lib/python2.7/site-packages/OctoPrint-1.2.0_dev_973_g3857e7e-py2.7.egg/octoprint/plugins/cura
|  Discovery (bundled) = /home/cubie/OctoPrint/venv/lib/python2.7/site-packages/OctoPrint-1.2.0_dev_973_g3857e7e-py2.7.egg/octoprint/plugins/discovery
|  GPX (0.3.1-9.g64586f1) = /home/cubie/OctoPrint/venv/local/lib/python2.7/site-packages/OctoPrint_GPX-0.3.1_9.g64586f1-py2.7-linux-armv7l.egg/octoprint_GPX
|  Plugin Manager (bundled) = /home/cubie/OctoPrint/venv/lib/python2.7/site-packages/OctoPrint-1.2.0_dev_973_g3857e7e-py2.7.egg/octoprint/plugins/pluginmanager
|  Software Update (bundled) = /home/cubie/OctoPrint/venv/lib/python2.7/site-packages/OctoPrint-1.2.0_dev_973_g3857e7e-py2.7.egg/octoprint/plugins/softwareupdate
|  Virtual Printer (bundled) = /home/cubie/OctoPrint/venv/lib/python2.7/site-packages/OctoPrint-1.2.0_dev_973_g3857e7e-py2.7.egg/octoprint/plugins/virtual_printer
(...)

In the web browser, at http://<cubian_ip>:5000, login in and add a new device on the left panel:
select Serial Port /dev/ttyACM0 > Baudrate 115200 > everything else auto > Connect
... and you should get a Machine State: Operational :)

Now from here, you can create startup scripts - in my case, I just use screen and run the octoprint command on a detached terminal.


The base for this set up is this guide from Octprint, for the Raspberry Pi

https://github.com/foosel/OctoPrint/wiki/Setup-on-a-Raspberry-Pi-running-Raspbian

...and Mark Walker's work on the GPX Plugin, essential for connecting this printer with Octoprint

https://github.com/markwal/OctoPrint-GPX


As for doing some 3D printing with this set up: check out the next post!


 






3D Printing

Recently I've decided to buy a 3D printer. Completely unaware of all the complexities behind 3D printing, I set out to choose one.

Although 3D printers have been around for a while now, buying one can be a challenging task, from price tag to print area size, print detail, print speed... etc etc etc etc.

First of all, there are a couple of websites which help a lot:



  • https://www.3dhubs.com/
  • http://www.thingiverse.com/
Between these two, you should find everything you need to get started.

So, since my budget wasn't that high, I eventually decided to buy a CTC Dual Extruder Printer.

https://www.3dhubs.com/3d-printers/ctc-3d

The reviews are mixed everywhere, there's people complaining about reliability, customer service and then the success cases... oh well, I decided to take a gamble.

I got it from ebay, shipped from Hamburg, and about a week later, I had it in my study!

I still have pretty much everything to learn from 3D printing, but after printing a couple of models, I'm actually pretty pleased with the quality, functionality and practicality of it...! :)

There are quite a few youtube videos out there about this printer, basically it's already pre-assembled, all you have to do is screw in the extruders head and set up the filament spool.

A couple of advices with this: take your time. Read and watch as much as you need to feel comfortable with the device.
If you feel the need to peel stuff off - don't! Make sure you're supposed to.

I'm still to try out the second extruder, different materials, etc. etc. etc. - but so far, one weekend in and I've been having quite a lot of fun with this printer!

Saturday 14 February 2015

QtQuick3D and SailfishOS (Jolla)

Recently I've been doing some work with Blender and since I have a soft spot for Qt and there was a Jolla phone laying around, I decided to do some research into how to get already made 3D models to work within a SailfishOS App. 

And the result was impressive - not just visually, but also code-wise:  



This example is from QtStudios and the source code I got was QtQuick1 - so I decided to try and integrate it in a normal SailfishOS App. The original QtQuick3D tutorial is available here:



What I found best about all this was that the pre-made 3D model could be imported and handled in QML, rather than C++ only - although not sure if Jolla would allow for this particular Qt Module to be used in a Jolla Store published app.

Regardless, it does make way for some interesting developments especially by combining it with Blender, the open source project!

In the meantime, if you own a Jolla phone and wish to try this out, go grab my version using either of the links below:

Jolla SailfishOS variant:


git@bitbucket.org:wickwire/sailfishos-qtquick3d-example.git git@gitlab.com:wickwire/SailfishOS-QtQuick3D-Example.git

Monday 9 February 2015

Cubieboard + Gitlab Update

... And my Cubieboard A20 has been running Gitlab and managing code for 19 days and 15min, without a hitch! ;)

Tuesday 20 January 2015

Cubieboard + Gitlab

I like hosting my pet projects on bitbucket.org. The free account includes both private and public projects, there's a wiki section, so far I've had zero issues with their services...

But recently I considered mirroring the projects there to other similar git cloud solutions, for backup.

After some google searching, I could just configure my local git repositories (on my PC) to "multipush" to bitbucket.org and gitlab.com (the other similar git cloud solution I ended up going for).

However, I had to replicate my "multipush" configuration accross any machine I would work at, as well as be prompted for my ssh passphrase about 4 times on each push action - and on top of that, if anyone else were to work with me collaboratively, we would all have to be extra careful in updating the cloud instances and make sure that one cloud service wouldn't get a different history than the other.

So, I decided to invest some more time with the issue and came up with what I consider to be, the ideal approach, in my case anyways:



So basically, I'm using a Cubieboard to run a Gitlab installation (as Gitlab exists both as a cloud service and as open source software that you can install and run privately), everyone pushes to that instance, and that instance alone communicates with the cloud services.

This clears any potential cloud service history mismatches as there is only one git server frontend to the developers, and ensures code replication/backup to multiple services on the cloud as well.

Note that while this setup is working, it might be worth it to consider the total volume of code generation, developers involved, etc. and replace the Cubieboard with something more robust if needed, in the long run, if that's you.

But anyways, this post is mainly about code versioning, with cloud replication, using free services and relatively cheap and low power consuming infrastructure - and Cubieboard is handling itself after 3 days non-stop usage, with a total 490MB RAM being used by the system.

That said, I'll be including my notes throughout the whole process, it took a while to get everything working, there are hacks along the way and first and foremost, the online resources I based my guide on:


(Using Cubieboard A20 with Cubian X1 nano headless)


Table of Contents






 useradd -d /home/git -m -s /bin/bash -G sudo git
 passwd git


 ssh git@Cubian.local -p36000
 cd ~


 sudo apt-get install git ruby patch ruby1.9.1-dev libmysqlclient-dev libmysqld-dev libicu-dev build-essential mysql-server redis-server libpq-dev


 wget http://nodejs.org/dist/v0.10.35/node-v0.10.35.tar.gz
 tar xvzpf node-v0.10.35.tar.gz
 cd node-v0.10.35
 ./configure --without-snapshot
 make -j3
 sudo make install


 mysql -u root -p
CREATE USER 'gitlab'@'localhost' IDENTIFIED BY 'gitlab';
SET storage_engine=INNODB;
CREATE DATABASE IF NOT EXISTS `gitlabhq_production` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`;
GRANT SELECT, LOCK TABLES, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON `gitlabhq_production`.* TO 'gitlab'@'localhost' IDENTIFIED BY 'gitlab';
quit


 cd ~
 sudo gem install bundler --no-ri --no-rdoc
 git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 7-1-stable gitlab
 cd gitlab
cp config/gitlab.yml.example config/gitlab.yml
 nano config/gitlab.yml
host: localhost #or 192.168.1.10, using static dhcp with the LAN router
port: 4343

    # If you use non-standard ssh port you need to specify it << cubian sets sshd port to 36000, keeping it
    ssh_port: 36000

chown -R git log/ tmp/
chmod -R u+rwX log/ tmp/
mkdir ~/gitlab-satellites
chmod u+rwx,g=rx,o-rwx ~/gitlab-satellites
chmod -R u+rwX tmp/pids/ tmp/sockets/ public/uploads

cp config/unicorn.rb.example config/unicorn.rb

nano config/unicorn.rb
listen "/home/git/gitlab/tmp/sockets/gitlab.socket", :backlog => 64
listen "localhost:4343", :tcp_nopush => true #or 192.168.1.10, using static dhcp with the LAN router

cp config/initializers/rack_attack.rb.example config/initializers/rack_attack.rb
git config --global user.name "GitLab"
git config --global user.email "mymail@gmail.com"
git config --global core.autocrlf input
cp config/database.yml.mysql config/database.yml
nano config/database.yml
...set DB preferences here...


nano Gemfile
#gem "therubyracer"

nano Gemfile.lock
    therubyracer (0.12.0) << delete
      libv8 (~> 3.16.14.0) << delete


 bundle install --no-deployment --path vendor/bundle
 bundle install --deployment --without development test postgres aws

 confirm that the redis daemon is running (should be, at this point) > netstat -an | grep 6379

 bundle exec rake gitlab:shell:install[v1.9.6] REDIS_URL=redis://localhost:6379 RAILS_ENV=production
 bundle exec rake gitlab:setup RAILS_ENV=production
login.........admin@local.host
password......5iveL!fe

 cp lib/support/init.d/gitlab ~/gitlab-start-stop (start as user git)
 cd ~
 ./gitlab-start-stop start (wait for a few minutes for it to start and release the cli)
 cd gitlab
 bundle exec rake gitlab:env:info RAILS_ENV=production
 bundle exec rake assets:precompile RAILS_ENV=production

 as root: cp /home/git/gitlab/lib/support/logrotate/gitlab /etc/logrotate.d/gitlab


 nano gitlab/config/gitlab.yml
 -> email_from: <valid_email_address>
 nano gitlab/config/environments/production.rb
 -> change sendmail to smtp
 config.action_mailer.delivery_method = :smtp

 cp gitlab/config/initializers/smtp_settings.rb.sample gitlab/config/initializers/smtp_settings.rb
 configure an email account (gmail example)
 config.action_mailer.smtp_settings = {
  :address              => "smtp.gmail.com",
  :port                 => 587,
  :domain               => 'gmail.com',
  :user_name            => 'account@gmail.com',
  :password             => 'password',
  :authentication       =>  :plain,
  :enable_starttls_auto => true
 }

 restart gitlab


 http://192.168.1.10:4343

 username: root << in my case, admin@local.host didn't work, root did
 password: 5iveL!fe


 The user should now receive the password at his valid email address (and possibly in Junk/Spam)


 On Cubian, as git user:
 cd ~
 nano gitlab-shell/config.yml
 gitlab_url: http://192.168.1.10:4343/

 restart gitlab server

 Cubian sshd runs on port 36000, so on the client, edit ~/.ssh/config if you wish to facilitate things:

 Host 192.168.1.10
 Hostname 192.168.1.10
     Port 36000

 cd ~
 sudo cp gitlab-start-stop /etc/init.d/
 sudo -s
 update-rc.d gitlab-start-stop defaults


Cubian:

 git user, generate ssh keypair without passphrase
 gitlab.com/bitbucket.org, add id_rsa.pub from the git user

 from Cubian, test ssh access:
 ssh git@gitlab.com >> Welcome to GitLab, Wickwire!
 ssh git@bitbucket.org >> logged in as wickwire.

 on Cubian, configure remotes for the gitlab server
 for each repository, done once:

cd ~/repositories/wickwire/raspberry-pi-qrdecoder.git
cat config

[core]
repositoryformatversion = 0
filemode = true
bare = true

[remote "gitlab"]
    url = git@gitlab.com:wickwire/raspberry-pi-qrdecoder.git
    fetch = +refs/heads/*:refs/remotes/gitlab/*
    fetch = +refs/tags/*:refs/tags/*
    autopush = true

[remote "bitbucket"]
    url = git@bitbucket.org:wickwire/raspberry-pi-qrdecoder.git
    fetch = +refs/heads/*:refs/remotes/bitbucket/*
    fetch = +refs/tags/*:refs/tags/*
    autopush = true

cat hooks/post-receive
#!/bin/bash

for remote in $(git remote); do
        if [ "$(git config "remote.${remote}.autopush")" = "true" ]; then
                git push "$remote" --all -u
                git push "$remote" --tags
        fi
done

chmod a+x hooks/post-receive

gitlab reload

On client, first time synching local Gitlab and remotes:

 git remote -v
 git remote rm origin
 git remote add origin <remote repo git url>
 git push -u origin --all # pushes up the repo and its refs for the first time
(repeat for all the cloud git services)
 git remote rm origin
 git add origin <local gitlab server repo>

from here, add content -> git add -A -> git commit -m "msg" -> git push - and it should all work, your code should be safely pushed to all instances: the Cubian GitLab and the cloud services.


This was a little trickier as editing wiki pages using the web browser didn't seem to trigger any Cubian GitLab repository hooks, and the web hook setup for GitLab didn't seem to help either - so I ended up using a "quick and dirty hack" to make it work:

Cron job running every 5min on user git, just to push any new changes at the Cubian GitLab Wiki repo

clone the bitbucket wiki first and manually push it to gitlab Cubian and gitlab.com

git clone git@bitbucket.org:wickwire/raspberry-pi-qrdecoder.git/wiki
cd wiki
#replace the bitbucket origin with the gitlab.com origin
git remote rm origin
git remote add origin git@gitlab.com:wickwire/raspberry-pi-qrdecoder.wiki.git
#force initial push to gitlab.com
git push --force origin --all
#replace the gitlab.com origin with the gitlab cubian origin
git remote rm origin
git remote add origin ssh://git@192.168.1.10:36000/wickwire/raspberry-pi-qrdecoder.wiki.git
git push --force origin --all

On Cubian Gitlab, as git user:

~/repositories/wickwire/raspberry-pi-qrdecoder.wiki.git

 cat config
[core]
        repositoryformatversion = 0
        filemode = true
        bare = true

[remote "gitlab"]
    url = git@gitlab.com:wickwire/raspberry-pi-qrdecoder.wiki.git
    fetch = +refs/heads/*:refs/remotes/gitlab/*
    autopush = true

[remote "bitbucket"]
    url = git@bitbucket.org:wickwire/raspberry-pi-qrdecoder.git/wiki
    fetch = +refs/heads/*:refs/remotes/bitbucket/*
    autopush = true



cat hooks/post-receive-crontab
#!/bin/bash

WORKDIR=`dirname $0`
cd $WORKDIR
for remote in $(git remote); do
        if [ "$(git config "remote.${remote}.autopush")" = "true" ]; then
                git push "$remote"
        fi
done

git user cron:

*/5 * * * * /home/git/repositories/wickwire/raspberry-pi-qrdecoder.wiki.git/hooks/post-receive-crontab >/dev/null 2>&1

All new entries on the wiki for this repo, using the traditional GitLab WebUI will be pushed to the cloud git repositories, every 5 minutes.



And that's it!

If you've survived this long, then you should have a working GitLab server running on your Cubieboard and while pushing code or adding/updating wiki content to it, all changes should be pushed to the cloud as well! :)