AdSense

Sunday, 30 August 2020

Home Automation with a Raspberry PI and ESP8266, part 2: A simple sensor (ESP8266)

(Deutsche Version) As the first project, I want to show my temperature and humidity sensors. I use an ESP8266 who reads a Si7021 sensor. The Si7021 is connected with a 4 pin cable to the ESP on pins D1-D4, as you can see in the image:

Additionally, you have to connect the pin D0 to RST, so deep sleep works, which we will use later. Using quite cheap phone chargers, I used a capacitor parallel to G and 3V.

This is placed in a 3d printed housing that you can find on thingiverse: https://www.thingiverse.com/thing:4583759. The sensor is fixed with the small hook in the housing. afterwards the ESP is placed on top and the lid fixes everything. The open side is suited to connect a phone charger.



The code is comparable to the one on my last post about this topic, https://physudo-e.blogspot.com/2019/07/wifi-thermometer-with-dht22-and-eps8266.html. In the setup part, the wifi is connected. If this does not work, the ESP is resetted after 100 seconds. Additionally, the Si7021 sensor is initialized.

In loop, if the WiFI is connected (otherwise the ESP is resetted), the temperature and humidity is measured. If anything goes wrong here, the ESP is resetted, too. Afterwards, everythin is sent via http request to the Raspberry PI as described in the previous post (https://physudo-e.blogspot.com/2020/08/home-automation-with-raspberry-pi-and.html).

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
const char* ssid     = "WIFI SSID";
const char* password = "WIFI PASSWORD";

#include "Adafruit_Si7021.h"

Adafruit_Si7021 sensor = Adafruit_Si7021();

void setup()
{
  Serial.begin(9600);

  Serial.print("Your are connecting to;");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  int resetCtr = 0;
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    resetCtr ++;
    Serial.print(".");
    if (resetCtr > 200)
    {
      ESP.restart();
    }
  }

  pinMode(D0, WAKEUP_PULLUP);
  pinMode(D3, OUTPUT);
  pinMode(D4, OUTPUT);
  digitalWrite(D3, HIGH);
  digitalWrite(D4, LOW);
  delay(500);

  while (!sensor.begin())
  {
    Serial.println("Did not find Si7021 sensor!");
  }

  digitalWrite(D3, LOW);
}



void loop() {
  if (WiFi.status() != WL_CONNECTED)
  {
    ESP.restart();
  }

  if (WiFi.status() == WL_CONNECTED)
  {
    Serial.println("");
    Serial.println("Your ESP is connected!");
    Serial.println("Your IP address is: ");
    Serial.println(WiFi.localIP());

    digitalWrite(D3, HIGH);
    delay(500);
    float t = sensor.readTemperature();
    Serial.print("Temperature: ");
    Serial.println(t);
    float h = sensor.readHumidity();
    Serial.print("Humidity: ");
    Serial.println(h);
    if (isnan(t))
    {
      t = sensor.readTemperature();
    }
    if (isnan(h))
    {
      h = sensor.readHumidity();
    }
    digitalWrite(D3, LOW);

    if (isnan(t))
    {
      ESP.restart();
    }
    if (isnan(h))
    {
      ESP.restart();
    }
    

        
    HTTPClient http;
    char requestString[255] = "";
    sprintf(requestString, "http://raspberrypi/SendValues.php?name=Temperatursensor_1&split=1&data=%f,%f", t, h);    
    http.begin(requestString);
    int httpCode = http.GET();
    Serial.println(httpCode);

    if (httpCode > 0)
    {
      String payload = http.getString();
      Serial.println(payload);
    }

    http.end();

    ESP.deepSleep(300e6); 
    delay(300000);
    ESP.reset();
  }
  else
  {
    Serial.println("");
    Serial.println("WiFi not connected");
    delay(1000);
  }
}

Home Automation with a Raspberry PI and ESP8266, part 1: Basics (Raspberry PI)

(Deutsche Version) Today, I want to start presenting my smart home system. I started half a year ago and by now, the system has grown quite big. The current system consists of:

  • 6 temperature- and humidity sensors inside
  • 3 temperature- and humidity sensors outside
  • 2 temperature- and humidity sensors in our terrarium
  • 1 CO2 sensor
  • 5 switchable plug sockets
  • 3 switchable lamps
  • 1 switch for the input of the sound system
  • Sensors at the washing mashine and tumble dryer
  • Microphone and two cameras at the 3d printer
  • Dashboard as website on an old tablet resp. on the smartphone
  • Telegram bot with automatic alerts and commandos

The basic for everything is a Raspberry PI 4, who acts as a server in the WiFi. All data is stored here, the website is placed here and all sensors communicate with the Raspberry. You don't have to setup much on the raspberry, I installed the apache2 webserver, you can find a lot of tutorials on this topic on the internet. Basically it can be condensed to this one command:

sudo apt install apache2

Additionally, I installed apache2 for php with this command:

sudo apt-get install php libapache2-mod-php

These are all the requirements on the Raspberry. I recommend to setup the folder /var/www/html/ as a network share, then you can access all files and scripts from other computers. Additionally, you should create the folder /var/www/html/data/, all data files are located here.

Now we can start with the scripts. I will only describe the basic script to send data, all other modifications and scripts will be presented with the relevant posts. To send data, I use the file "SendValues.php", which requests the following GET parameters from the sensor:

  • "name", the name of the sensor, e.g. "TemperatureSensor_1"
  • "split", how the data should be split. The problem would be files accumulating the data over years, making them very big and hard to handle. Therefore, the data is split by year, month or day. Split 0 means no splitting, 1 equals one file per year, 2 one file per month and 3 one file per day
  • "data", the relevant data, separated by comma, e.g. for a temperature and humidity sensor: 24.1,54.6

The script consists of the following parts. At first the header:

<html>
 <head>
  <title>Send Sensor Values</title>
 </head>
 <body>
  <?php 

Afterwards the relevant code. Here the data is read and the current date is determined:

$name = htmlspecialchars($_GET["name"]);
$split = htmlspecialchars($_GET["split"]);
$data = htmlspecialchars($_GET["data"]);

$date = gmdate("Y-m-d") . "T" . gmdate("H:i:s.u") . "Z";

Now, a [name]_last.csv file is created, which holds the newest value:

$file = "data/".$name."_last.csv";
$Saved_File = fopen($file, 'w');
fwrite($Saved_File, $date . "," . $data . "\r\n");
fclose($Saved_File);

Next, the splitting is performed. Therefore the filename is created, [name]_[year]-[month]-[day].csv. To have an overlap between two files, the next file is also created, for the next year, next month, next day and already holds the values. If e.g. the last year is requested this guarantees that every file contains at least one year of data, not only the values starting from January 1st. $file1 is the current file, $file2 the one for the next time period.

$file = "data/".$name.".csv";

if ($split == "1")
{
  $file = "data/".$name."_" . gmdate("Y") . ".csv";
  $file2 = "data/".$name."_" . gmdate("Y", strtotime("+1 year")) . ".csv";
}
if ($split == "2")
{
  $file = "data/".$name."_" . gmdate("Y-m") . ".csv";
  $file2 = "data/".$name."_" . gmdate("Y-m", strtotime("+1 month")) . ".csv";
}
if ($split == "3")
{
  $file = "data/".$name."_" . gmdate("Y-m-d") . ".csv";
  $file2 = "data/".$name."_" . gmdate("Y-m-d", strtotime("+1 day")) . ".csv";
}

Now the data is saved. If "split" is 0, the saving into the second file is skipped as there only exists one single file for the whole time.

$Saved_File = fopen($file, 'a');
fwrite($Saved_File, $date . "," . $data . "\r\n");
fclose($Saved_File);
if ($split == "0")
{
}
else
{
  $Saved_File = fopen($file2, 'a');
  fwrite($Saved_File, $date . "," . $data . "\r\n");
  fclose($Saved_File);
}

This already was the whole code, we now have to close all the tags and then SendValues.php is completed:

  ?>
 </body>
</html>

This is all you need on the server site, now the sensors can send their data. To test this, you can put the following text into your browser within your WiFI, this should create the files TemperatureSensor_1_last.csv, and two additional files with the current and the next year at the end:

http://raspberrypi/SendValues.php?name=TemperatureSensor_1&split=1&data=25.3,64.59

For everyone not wanting to copy the code parts, here is the complete code:

<html>
 <head>
  <title>Send Sensor Values</title>
 </head>
 <body>
  <?php
 
$name = htmlspecialchars($_GET["name"]);
$split = htmlspecialchars($_GET["split"]);
$data = htmlspecialchars($_GET["data"]);

$date = gmdate("Y-m-d") . "T" . gmdate("H:i:s.u") . "Z";

$file = "data/".$name."_last.csv";
$Saved_File = fopen($file, 'w');
fwrite($Saved_File, $date . "," . $data . "\r\n");
fclose($Saved_File);

$file = "data/".$name.".csv";

if ($split == "1")
{
  $file = "data/".$name."_" . gmdate("Y") . ".csv";
  $file2 = "data/".$name."_" . gmdate("Y", strtotime("+1 year")) . ".csv";
}
if ($split == "2")
{
  $file = "data/".$name."_" . gmdate("Y-m") . ".csv";
  $file2 = "data/".$name."_" . gmdate("Y-m", strtotime("+1 month")) . ".csv";
}
if ($split == "3")
{
  $file = "data/".$name."_" . gmdate("Y-m-d") . ".csv";
  $file2 = "data/".$name."_" . gmdate("Y-m-d", strtotime("+1 day")) . ".csv";
}
$Saved_File = fopen($file, 'a');
fwrite($Saved_File, $date . "," . $data . "\r\n");
fclose($Saved_File);
if ($split == "0")
{
}
else
{
  $Saved_File = fopen($file2, 'a');
  fwrite($Saved_File, $date . "," . $data . "\r\n");
  fclose($Saved_File);
}

  ?>
 </body>
</html>

Tuesday, 11 August 2020

Machine Learning for a camera surveilled 3d printer

(Deutsche Version) It's been now over a year since the last post and I did lots of projects, especially with the multi-colour upgrade for my Ultimaker 2+. Today, I want to share a project that is part of this, but also part of my IoT Home Automation system: A (two) camera based surveillance for my 3d printer with automated recognition of states.

First of all: the cameras. I have two ESP32-Cam modules where you can find endless tutorials on the internet on how to program these. I then added them to my 3d printer. The first camera is on top, with a 3D-printed fixture you can find here: https://www.thingiverse.com/thing:3899159

The second camera is placed in the 3D printer with tape, and I slid a 45° block below the camera module to get the right angle.

These cameras produce a new image roughly every 3 minutes, so I have a lot of training data by now. The images look like this:



The images can be classified into different categories:

  1. Idle: The printhead is in its parking position and the printbed is empty
  2. Preparing: The printhead is in the front left position and the printer is heating up
  3. Printing: I don't really have to explain this I guess
  4. Finished: The printhead is in its parking position and the printbed is not empty
  5. Problem: A distance between the printbed or the current object and the nozzle is visible
  6. Maintenance: My hands are in the printer, the printhead is disassembled or not in its parking position
  7. Off: All lights are switched off and the image is only dark

Camera 1 can't really decide whether it's printing or problem, so this camera cannot detect "problem", camera 2 can't distinguish between idle and finished, so this camera cannot detect "finished".

I sorted the first images I had into the 7 categories and then trained a neural net on them. My architecture of the net (in Tensorflow, Python) looks like this:

model = models.Sequential()
model.add(layers.Conv2D(32, (5, 5), activation='relu', input_shape=(128, 128, 3)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(32, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(32, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(32, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(32, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(7))

It is designed for the input of 128x128 pixel images with 3 colours and consists of 5 convolutional layers, each with a max pooling layer afterwards and then one fully connected layer with 64 neurons which leads to the output layer with 7 neurons.

To further optimise the detection, I added a second net that uses images of the input 64x64 pixels and thus has only 4 convolutional layers. The result percentages for each category of the two nets are added (and divided by 2), which increases the accuracy. In the end, this result is obtained for both cameras and again added, furthermore there is a microphone inside the printed which measures the noise level and can distinguish whether the printhead fan is on or off and thereby delivers another input. The total results then creates a forecast for the status of the printer. As described in the previous post, this status is then sent to my IoT system which alerts me if

  • The printer status changes to "Problem"
  • The printer status changes to "Finished"

Tuesday, 2 July 2019

WiFi thermometer with the DHT22 and EPS8266-12E

(Deutsche Version) I should be posting more stuff about the printer but I just worked on the ESP8266-12E and realised a super easy WiFi thermometer (using an EPS8266-12E as a web client which sends to an apache server on a raspberry pi), so I wanted to share this here.


1. The ESP8266-12E
The ESP8266-12E is an Arduino like microcontroller which has an integrated WiFi controller. If you look for it on google, you'll find many sources to aquire it. The great thing about this EPS8266 is that you can program it with the Arduino software, so all your libraries work, too!

2. Set up the Arduino IDE for the ESP8266-12E
First you should install the CH340 driver. There are many tutorials for this on the internet so I will not explain this. After installing the driver, you have to switch to the Arduino settings (I only have a german Arduino IDE but I guess you should be able to figure out where to click):

Here you add the board manager URL:
http://arduino.esp8266.com/stable/package_esp8266com_index.json

Afterwards, you can download the settings for the boards in the board manager:

Look for "ESP8266" and install it:

Now, everything should be set up and we can choose the board, I used "NodeMCU 1.2 (ESP8266-12E Module)":


3. The code
The code is quite straight-forward. You have to put in your WiFi login data, afterwards the DHT22 sensor is initialised. In "loop", the connection to the WiFi is tested. If a connection is established, the sensor measures temperature and humidity (float t and float h), these values are stored in a string (requestString) and then sent as HTTP get request to the server. The code for the server is posted below.

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
const char* ssid     = "***";
const char* password = "***";   
int wifiStatus;
    
#include "DHT.h"
#define DHTPIN D2
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(9600);
  // put your setup code here, to run once:

  Serial.print("Your are connecting to;");
  Serial.println(ssid);
  
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }

  dht.begin();
}

void loop() {
  // put your main code here, to run repeatedly:
  wifiStatus = WiFi.status();
  
  if(wifiStatus == WL_CONNECTED){
    Serial.println("");
    Serial.println("Your ESP is connected!");  
    Serial.println("Your IP address is: ");
    Serial.println(WiFi.localIP()); 
    float t = dht.readTemperature(); 
    float h = dht.readHumidity(); 
    HTTPClient http;
    char requestString[255] = "";
    sprintf(requestString, "http://webServer.de/Send.php?name=TemperatureSensor&data=%f,%f", t, h);
    http.begin(requestString);  //Specify request destination
    int httpCode = http.GET();                                                                  //Send the request
    
    if (httpCode > 0) 
    { //Check the returning code
      String payload = http.getString();   //Get the request response payload
      Serial.println(payload);                     //Print the response payload
    }
    
    http.end();   //Close connection
    
    delay(300000);
  }
  else{
    Serial.println("");
    Serial.println("WiFi not connected");
    delay(1000);
  }
}

4. The Sserver code
An apache server is running on my raspberry pi. In /var/www, there is a file "Send.php", which simply receives sensor data and saves this to .csv files. The sensor tells its name in the get command, this is the filename where the data is stored. The current time is added and stored together with the data at the end of the file. In this case, this is the temperature in °C and the humidity in %.

<html>
 <head>
  <title>Send Sensor Values</title>
 </head>
 <body>
  <?php

$name = htmlspecialchars($_GET["name"]);
$data = htmlspecialchars($_GET["data"]);

$date = date("Y-m-d") . "T" . date("H:i:s.u") . "Z";

$file = "data/".$name.".csv";
$Saved_File = fopen($file, 'a');
fwrite($Saved_File, $date . "," . $data . "\r\n");
fclose($Saved_File);

  ?>
 </body>
</html>

Thursday, 20 June 2019

2.85mm Filament Geared Bowden Extruder Feeder

(Deutsche Version) As promised, I will now explain all the single parts of my multi-material Ultimaker. Today, I will explain the feeder. Unfortunately, I did not find a good solution, so I had to build my own feeder. The feeder consists of several 3D printed parts.

The following parts are required for the extruder:
  • 3D printed parts: https://www.thingiverse.com/thing:3703063
  • Several parts from ebay or other shops (I suggest using the pictures below to buy the correct parts)
    • A 1.75 mm metal feeder ("MK8 Metal Bowden Extruder" on ebay)
    • A 4/6 mm bowden tube (PTFE, inner diameter 4 mm, outer diameter 6 mm)
    • A bowden coupler (comparable to the original part at the Ultimaker 2+, "Bowden tube clip" on ebay)
    • Extruder gear
    • 2 x 26 teeth extruder gear
    • 2 x bearings 625ZZ (16x5x5 mm)
    • Nema17 motor, 1.7A, 0.9°
  • Screws
    • 3 x M3x10
    • 3 x M3x30 (longer screws would be better, e.g. 35 mm length)
    • M4x30
  • Aluminum rod, 5mm diameter (I only found 5.3 mm, this is also fine)
At first, the motor is fixed on the main part.

Next, the feeder has to be adapted for 2.85 mm, therefore a 5 mm drill is used. Then the edges are rounded a bit.

Afterwards, the screw that holds the spring has to be shortened, otherwise the two screws will touch before the spring can build up enough pressure.

The next step is mounting the bowden coupler and bowden tube to the main part.

Now, the feeder is mounted with a M3x10 screw to the main part, from the other side a bearing is placed in the designated holder and both things are fixed with this screw. Important: The head of the screw has to be inside the metal part, otherwise, there could occur problems later.

Then, the arm of the feeder is built up (here you need the M4 screw) and mounted, therefore the three M3x30 screws are mounted in the other direction as the M3x10 screw. Afterwards, the spring is placed in the arm.

Now you need a 52 mm long piece of the aluminum rod. Mount the extruder gear with 7 mm distance to one end.

The large sleeve is placed on the rod, then the rod is placed into the bearing. You might need to push the arm a bit so it fits well.

If you fixed the M3x30 screws with nuts, you should remove them now. The second bearing is placed on the axis and the suitable holder is placed on top. You can fix this with the lower screw by placing the nut there, if you increase the pressure from the string with the M4 screw, the other screws will not fall out any more.

Afterwards, the large black clip is mounted, after this you can add the final two nuts to hold everything together.

Now we go to the other side of the extruder. The two extruder gears with 26 teeth are mounted in the big gears, you can use a small drop of glue to prevent them from sliding apart. The small sleeve is placed on the rod, otherwise the big gear will grind on the holder for the bearing and start to melt together. The gears are now mounted on the rod respectively the axis of the motor. Use some pressure from below on the axis to fix everything tight together.

Your extruder is now completed and can be used. Of course, you can use this extruder for any 3D printing issue that is not linked to multi material printing.

If I did not explain everything precisely or if I forgot to mention something or some material you need, please tell me so I can add this to this post.

Sunday, 16 June 2019

Fully automatic multi-colour printing with the Ultimaker 2+

(Deutsche Version) As descirbed in my last post last november, I tackeled the topic of doing multi-colour printing with my Ultimaker 2+. Now, after several months I figured out a solution how to print multi-colour objects with an Ultimaker 2+. In this post, I want to describe the different components and then upload a post for every single component.

The basic principle is similar to my semi-automatic multi-colour printing, instead of having multiple nozzles like the Ultimaker 3, I onle use one nozzle and for every material change, the material gets pulled out and the next material is inserted into the nozzle. Therefore, I attached a Y-splitter behind the extruder to combine multiple bowden tubes. At the end of each bowden tube there is a filament feeder, meaning that for every colour I want to print simultaneously, I have to build up an own feeder. During the retraction of the material, the printer codes the next needed extruder in the movement so an external electronic can distinguish which motor has to be switched on next and then switches to this motor via a relais card. The whole project consists of the following parts:
  1. Y-splitter for the bowden tubes
  2. Multiple feeders
  3. External electronics to swich the extruders
  4. Scripts in Slic3r
The first thing is solved quite easily, therefore I created designs for 4, 8 and 16 bowden tubes and uploaded them to thingiverse. You probably have to tune the printing properties (horizontal expansion) so the adaptors fit.
https://www.thingiverse.com/thing:3695457

Saturday, 10 November 2018

Semi-automatic Multi-Colour Printing with the Ultimaker 2+

(Deutsche Version) For nearly 2 years nothing has been happening on this blog and it's time to change that. The current project I'm working on is to equip an Ultimaker 2+ for multi-material printing, being able to print up to 15 different colours. I will post more about that in the future, after finishing the project. Today, I want to present the pre-stage to this: A semi-automatic multi-colour printing Ultimaker 2+. The basic idea is to only use one nozzle and pull out the old material and then insert the next colour, similar to the Prusa i3 Multi-Material Upgrade.

What do I mean by semi-automatic? The printer is printing with a single colour. At one point, he stops, throws out the material and then waits till the next material is inserted. This is suitable for easy parts which consist of a basic colour and then, after reaching a certain height, change their colour. Examples for this could be some writing on an object, a traffic cone (https://www.thingiverse.com/thing:3207478) or in the area of tabletop terrain these farm fields (https://www.thingiverse.com/thing:3207486).

The big question is: What did I have to change at the printer? And the great answer is: Nothing! Therefore it was really easy to implement this multi-colour printing. I was using "Slic3r" as slicer because I can add user defined G-Code and the software is suitable for any amout of extruders. I will now explain step-by-step how my printing profiles in Slic3r looked like. First, the Printer Settings in Slic3r:

I used the following settings for every extruder:

In the area Custom G-code, I placed these snippets:
Start G-code
M109 S[first_layer_temperature] ; heat nozzle to first layer temperature and wait until reached
G21 ; metric values
G90 ; absolute positioning
M82 ; Extruder to Absolute
G28 ; home all axes
G1 X7 Y7 F6000 ; bring extruder to the front
G1 Z25 F2000 ; Raise Bed to Head
G92 E0 ; zero the extruded length
T0 ; Select Extruder 1
G92 E0 ; Zero Extrude L
G1 F200 E8 ; Extrude 16 @ 200mm/s
G92 E0 ; Zero Extrude L
G1 F50 E4 ; Extrude 16 @ 50mm/s
G92 E0 ; Zero Extrude L
G1 F20 E2 ; Extrude 2 @ 20mm/s
G1 X100 Y7 F6000 ; bring extruder to the front
G92 E0 ; Zero Extrude L
G92 E0 ; zero the extruded length again
End G-code
; Add Change Tool To Extruder 0 here

G92 E0 ; zero the extruded length
G1 E-2 F200 ; Extrude(Retract) -2mm @ 50mm/s
G28 ; home all
M104 S0 ; turn off heaters
M140 S0 ; turn off bed
M84 ; disable motors
Before layer change G-code
;XXX Before Layer Change
After layer change G-code
;LayerChange
G90 ; absolute positioning
G1 X190 Y190 F6000;

G92 E0 ; zero the extruded length
;G1 E7 F2100 ; Retraction compensation


;Prime Tower

;Prime Tower Routine
G91; Relative mode
G1 Z-1 F2100; Lower Head 1mm
G90 ; absolute positioning
G1 X180 Y190 F6000;
G91; Relative mode

;Rectangle around
G1 Y16 E7.1 F600
G1 X-128 E1 F1200
G1 Y-16 E0.1
G1 X128 E1
G1 Y-16 E0.1
G1 X-128 E1
G1 Y16 E0.1

;Prime Nozzle
;G1 X-128 F3600;No extrusion because part of border


G1 X16 Y-16 F6000
G1 Y32 E0.1 F1200
G1 X16  F6000
G1 Y-32 E0.1 F1200
G1 X16 F6000
G1 Y32 E0.1 F1200
G1 X16 F6000
G1 Y-32 E0.1 F1200
G1 X16 F6000
G1 Y32 E0.1 F1200
G1 X16 F6000
G1 Y-32 E0.1 F1200
G1 X16 F6000
G1 Y32 E0.1 F1200
G1 X16 F6000
;G1 E-7 F2100 ; Retract
G1 Y-32 E-6.9 F1200;No extrusion because part of border

G1 Z1 F2100; Raise Head 1mm

G90 ; absolute positioning
G92 E0 ; zero the extruded length


;Retract
;G92 E0
;LayerEnd
Tool change G-code
;XXX Tool Change
;M104 S100
G90 ; absolute positioning
G1 X190 Y190 F6000;

G92 E0 ; zero the extruded length
G1 E-399 F10000 ; Extrude(Retract) -500mm @ 50mm/s
G1 E-40[next_extruder] F30 ; Extrude(Retract) -1mm @ 1mm/s
G1 E-715 F10000 ; Extrude(Retract) -500mm @ 50mm/s

G92 E0 ; zero the extruded length
G1 F50 E-40 ; Extrude 8 @ 50mm/s

M0;

;M104 S[temperature_0]
G90 ; absolute positioning
G92 E0 ; zero the extruded length
G1 F50 E20 ; Extrude 8 @ 50mm/s

G92 E0 ; zero the extruded length
G1 E700 F10000 ; Extrude(Insert)500mm @ 50mm/s

G92 E0 ; zero the extruded length
G1 F50 E20 ; Extrude 16 @ 50mm/s


;Prime Tower

;Prime Tower Routine
G91; Relative mode
G1 Z-1 F2100; Lower Head 1mm
G90 ; absolute positioning
G1 X180 Y190 F6000;
G91; Relative mode

;Prime Nozzle
G1 Y1 F6000
G1 Y[next_extruder] F6000
G1 X-128 E2 F700
G1 Y-16 F6000
G1 X128 E2 F700
G1 Y-1 F6000
G1 Y-[next_extruder] F6000
G1 X-128 F6000

G1 X1 F6000
G1 X[next_extruder] F6000
G1 Y32 E0.2 F700
G1 X16 F6000
G1 Y-32 E0.2 F700
G1 X16 F6000
G1 Y32 E0.2 F700
G1 X16 F6000
G1 Y-32 E0.2 F700
G1 X16 F6000
G1 Y32 E0.2 F700
G1 X16 F6000
G1 Y-32 E0.2 F700
G1 X16 F6000
G1 Y32 E0.2 F700
G1 X16 F6000
G1 Y-32 E-6.8 F700

G1 Z1 F2100; Raise Head 1mm

G90 ; absolute positioning
G92 E0 ; zero the extruded length


;Retract
;G92 E0
;ToolEnd
Next thing are the Filament Settings for Filament and Cooling:







 
The largest block are the Print Settings with all their sub-categories:














You should place the correct path to the scripts. I had to write a post-script which edits my G-Code because Slic3r was adding T0, T1, ... for all the different extruders I don't have. If you feed your Ultimaker 2+ with a T1 command, the first (and only) extruder stops. The post script now does 2 things:
  • Replace all T1, T2, ... with T0
  • Compensate a retraction problem - Slic3r retracts tools which are not used and therefore pushes the material forwards into the nozzle after the tool change. This does not happen if the tool is used for the first time, because Slic3r did not pull out material from this tool yet. Therefore my post script checks whether an E7-command is there after a tool change and if not, adds this line to the G-Code
The post script is written in Octave (comparable to Matlab), you should also install this software. The post script "StartOctave.bat" looks like this:
C:\Octave\Octave-4.2.1\octave.bat C:\Slic3rSkripte\OctavePostScript.m %1
It basically calls the file "OctavePostScript.m":
s = argv(){1};

myfile = fopen("testOctave.txt", "w");
fprintf(myfile, "%s\r\n", s);
fclose(myfile);

%s = "I:\Traffic_Cone_Rings_Orange.gcode";
myfile = fopen (s, "r");
outText = [];
tline = fgetl(myfile);
i = 1;
outText{i} = tline;
while ischar(tline)
  i = i+1;
  outText{i} = tline;
 
 
  tline = fgetl(myfile);
end
imax = i;
fclose(myfile);

myfile = fopen(s, "w");
%fprintf(myfile, ";EDITED!\r\n");
insertLine = 0;
for i=1:imax
  tempLine = outText{i};
 
  if (size(tempLine,2) > 1)
    if (tempLine(1) == "T")
      outText{i} = "T0";
    end
  end
 
 
  if (strcmp(tempLine,";ToolEnd"))
    insertLine = 7;
  end
  
  if (insertLine > 0)
    insertLine = insertLine -1;
  end
 
  if (insertLine == 1)
    if (tempLine(4) == "E")
    else
      fprintf(myfile, "G1 E7.00000 F2100.00000\r\n");
      fprintf(myfile, "G92 E0 \r\n");
    end
  end

  fprintf(myfile, "%s\r\n", outText{i});
end
fclose(myfile);
Finally, an object has to be loaded into Slic3r. Now, right-click on it and choose settings and then "Load Part" to add further colour-objects. Here you can set which extruder the printer will be using. For first tests, you could use my thingiverse-links from above.

The source code is definitely improvable, if anyone has comments on this, please tell me. Always keep in mind that the code is built with the perspective of having an automatic material change, so some parts seem to be a bit complicated.