AdSense

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.

Sunday, 11 September 2016

Read DHT11 sensor with Arduino

(Deutsche Version) Some time ago, I bought a temperature and humidity sensor which is called DHT11. The sensor is easy to use and can be used with 3.3V or 5V. The sensor has four pins, for the normal operation, only three of them are needed.
The left pin (as you can see in the image) is connected to 5V, the pin on the right with GND. The left pin of the middle pins is the signal pin which can be connected with a random digital pin on the arduino (in my example, this is pin 2). Additionally, a 10k resistor is needed between the data pin and 5V.

Next, you need the corresponding library which you can download here: Download. In the arduino software the sensor can be read as it is shown in the following example. The source code should be self-explainatory. If a sensor with a higher precision is needed, you can use a DHT22, therefore you just have to adjust the DHTTYPE definition.

#include "DHT.h"
#define DHTPIN 2

#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);

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

  dht.begin();
}

void loop() {
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  
  Serial.print("Humidity: ");
  Serial.print(h);
  Serial.print(" %\t");
  Serial.print("Temperature: ");
  Serial.print(t);
  Serial.println(" *C ");

  delay(2000);
}

Sunday, 17 July 2016

3D printing profiles for the Ultimaker 2

(Deutsche Version) After a long time with no updates I want to introduce a new topic to this blog: 3D printing. I own an Ultimaker 2 and in this first post, I want to present the printing profiles I use. I only use black PLA from Innofill. This means that I do not have to fine tune the printing profiles if I buy new material because the properties of the material stay the same.

Ultimaker 2:
At the printer, I only set some small values. I have three profiles: Fast, Fine and Ultrafine. For all three of them I use a Heatbed Temperature of 70 °C. This get the PLA to stick to the platform. The Nozzle Temperatures are 210 °C for Fast, 195 °C for Fine and 172 °C for Ultrafine. This last temperature is really close to the melting point, this means that if the temperature in your house changes (summer / winter) you have to adjust this temperature, in the winter I usually have 175 °.


Printing profiles for Cura:
Usually, PLA does not need any cooling by the fans. If you activate this cooling, the print will warp upwards. Therefore the profiles Fast and Fine have a Minimum Fan Speed of 10%, whereas Ultrafine has 60%. This means that small structures are cooled quite good and the print does not melt during the printing process as the nozzle always stays at nearly the same position.
The Layer Height is 0.1 mm for Fast and 0.05 mm for Fine and Ultrafine. The Shell Thickness is 0.8 mm.
The printing speed is set to 25-40 for Fast, 20-25 for Fine and 10-25 for Ultrafine.

If anyone is interested in the profile files, you can download them here:
Fast
Fine
Ultrafine

Wednesday, 23 September 2015

nrf24l01+ with ATtiny84

(Deutsche Version) I already explained how to tun the wireless module nrf24l01+ with an Arduino or ATmega in an earlier post.  If you want to run the module with an ATtinyx4, e.g. the ATTiny84, you have to do some changes.

In this post, I want to explain how to set up a wireless communication between an Arduino and an ATtiny84 using the ping example of the Mirf library. The Arduino sends a ping signal, the ATtiny receives the signal and sends it back.

Before you start, you have to install the ATtiny cores for the Arduino IDE like I explained HERE.

Libraries needed

The wireless module nrf24l01+ uses SPI to communicate with the microcontroller. Unfortunately, the ATtiny has no hardware SPI so you have to use software to emulate the SPI connection. This is done using the so called Universal Serial Interface (USI). As usual there is a library for this, so you don't have to worry about that. Besides that, you need a modified version of the Mirf library. Both libs can be downloaded HERE. After extracting the folders "Mirf" and "SPI85" to the "libraries" folder of the Arduino IDE, you can use these libs.

Hardware

The wiring is pretty similar to the one in the example with the ATmega. CSN, CE, SCK, MOSI and MISO as well as VCC and GND have to be connected. Don't forget that the module runs with a voltage of 3,3V! The follwoing picture shows how the connect the wireless module to the ATtiny84.
  
Important: in the datasheet of the ATtiny you will find some pins called MISO, MOSI and SCK. These pins are only for connecting your programmer (e.g. the USBasp). The module has to be connected to USI-DI (corresponds to MISO), USI-DO (MOSI) and USCK (SCK). By default, the pins D4 to D6 are used for these pins. If you want, you can change these pins but you must not set USI-DI to the MISO pin of your programmer. The same applies for USI-DO and MOSI pin.

Software

The original "ping_client" example of the Mirf library runs on the Arduino. For the ATtiny, you have to use a slightly changed version of the "ping_server" example:

#include <SPI85.h>
#include <Mirf.h>
#include <MirfHardwareSpi85Driver.h>

// This USI was defined in SPI85.cpp
// Not to be confused with SPI (MOSI/MISO) used by ICSP pins
// Refer to page 61 of attiny84 datahseet
// USI pins could be redefined here
//#define USI-DO  5
//#define USI-DI  4
//#define USCK   6

#define CE    7    
#define CSN   3 

void setup(){

  
  /*   * Set the SPI Driver.   */

  Mirf.spi = &MirfHardwareSpi85;
    
  /*   * Setup pins / SPI.   */
  
  Mirf.cePin = CE;
  Mirf.csnPin = CSN;
  Mirf.init();
  
  /*   * Configure reciving address.   */
   
  Mirf.setRADDR((byte *)"serv1");
  
  /*   * Set the payload length to sizeof(unsigned long) the   * return type of millis().   *   * NB: payload on client and server must be the same.   */
   
  Mirf.payload = sizeof(unsigned long);
  
  /*   * Write channel and payload config then power up reciver.   */
   
  Mirf.config();

}

void loop(){
  /*   * A buffer to store the data.   */
   
  byte data[Mirf.payload];
  
  /*   * If a packet has been recived.   *   * isSending also restores listening mode when it    * transitions from true to false.   */
   
  if(!Mirf.isSending() && Mirf.dataReady()){

    /*     * Get load the packet into the buffer.     */
     
    Mirf.getData(data);
    
    /*     * Set the send address.     */
     
     
    Mirf.setTADDR((byte *)"clie1");
    
    /*     * Send the data back to the client.     */
     
    Mirf.send(data);
    
    /*     * Wait untill sending has finished     *     * NB: isSending returns the chip to receving after returning true.     */
      
    
  }
}

The only difference to the version for ATmega is that SPI85.h and MirfHardwareSpi85Driver.h are included and MirfHardwareSpi85 is chosen as SPI driver in the setup():
Mirf.spi = &MirfHardwareSpi85;

When you upload the code to the ATtiny using a programmer, the pinging Arduino should get a response from the ATtiny.


I had some problems flashing the ATtiny with the USBasp as soon as the wireless module was connected to the ATtiny. I think this happend because the module and the programmer use the same pins. I have to disconnect the voltage supply of the module while flashing, then everything works fine.

Tuesday, 22 September 2015

ATtiny and the Arduino IDE - RELOADED

(Deutsche Version) Some time ago, I published a post with the topic "ATiny and Arduino" in which I explained how to install the so called ATiny cores for Arduino to be able to program the ATtiny with the Arduino IDE.

Since I needed anohther core for my new projects, I wanted to write a short post about it, too. The core can be used for ATtiny25, ATtiny45, ATtiny85, ATtiny24, ATtiny44 and ATtiny84.

All the files you need can be downloaded HERE. After extracting the archive, copy the folder "tiny" to the folder "hardware" of your Arduino installation (e.g.  "C:\Programs\Arduino\hardware\tiny"). Open the subfolder "avr" in the folder "tiny" and rename the file "Prospective Boards.txt" to "boards.txt".

After restarting the Arduino IDE, you can choose the desired ATtiny. Since I use the german version of the IDE, I'm not sure how the menu is called in the english version. I think it sould be something like "Tools" - "Boards". Have a look at the screenshot if you can't find the right menu. The ATiny can now be programmed with the IDE using a programmer like the USBasp. It is important that the fuses of the ATtiny are set correctly and fit to the chosen settings.

Pinout can be found in the file "pins_arduino.c" in the folder "tiny\avr\cores\tiny".
For the ATtinyx4 it's for example:
//
//                                        +-\/-+
//                               VCC  1|    |14  GND
//                     (D  0)  PB0  2|    |13  AREF (D 10)
//                     (D  1)  PB1  3|    |12  PA1  (D  9)
//                               PB3  4|    |11  PA2  (D  8)
//  PWM  INT0  (D  2)  PB2  5|    |10  PA3  (D  7)
//    PWM        (D  3)  PA7  6|    |9   PA4  (D  6)
//    PWM        (D  4)  PA6  7|    |8   PA5  (D  5)        PWM
//                                       +----+

Tuesday, 10 February 2015

Serial communication with Matlab or C#

(Deutsche Version) In the last post, I showed how to read out a heartbeat sensor (Read out heartbeat sensor). In this post, I want to explain how to read this data with Matlab or C#. I want to start with Matlab. At first, you have to open a serial port:

s = serial('COM3');
fopen(s);


You simply have to plug in the number of your COM port. Afterwards you can read all existing characters:

str = fscanf(s);

Keep in mind that it can also occur that the Arduino has only sent half of its message when the computer is reading all existing characters, and in the next read instruction from the computer, the rest of the message (and possibly further messages) is read in. In the end you should close the port:

fclose(s);

Now, I want to explain how to do this in C#. Again, you have to open a port:

port = new SerialPort("COM3", 9600);
port.Open();

Afterwards, you can read in all existing characters (analog to the example with Matlab):

string indata = sp.ReadExisting();

In C#, you don't have to close the port because this happens automatically when closing the program.