Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also .

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also .
Commits on Apr 18, 2016
created new file for perl based print engine and configuration for that engine
started to introduce primitive samity-checks and configuration evaluation to printengime
untill further notice onyl Beaglebone black with Lightcrafter 4500 on HDMI will be supported.
Commits on May 07, 2016
….txt in zip archive

read overshoot from config file
defined overshoot default in config file
soem debugcode for new variables - will be removed later on
Showing with 484 additions and 1 deletion.
  1. +10 −1 js/main.js
  2. +2 −0 modules/g1.gcode
  3. +71 −0 modules/printengine.cfg
  4. +354 −0 modules/printengine.pl
  5. +47 −0 modules/send.pl
@@ -454,7 +454,16 @@ function startSlicing() {
if (settings.get('slicer.zip')) {
zipFile = new JSZip();
zipFolder = zipFile.folder('slices');
zipFile.file("README.txt", 'Generated by SLAcer.js\r\nhttp://lautr3k.github.io/SLAcer.js/\r\n');
ontime = parseInt(times.on);
offtime = parseInt(times.off);
layerheight=settings.get('slicer.layers.height');
zipdelimiter='\"'
ziptext1= '#Generated by SLAcer.js\r\n#http://lautr3k.github.io/SLAcer.js/\r\nlayer_height='+zipdelimiter+layerheight;
ziptext2='\r\nexposure_time='+zipdelimiter+ontime;
ziptext3= '\r\nresin_settling_time='+zipdelimiter+offtime;
ziptext= ziptext1+zipdelimiter+ziptext2+zipdelimiter+ziptext3+zipdelimiter;

zipFile.file("README.txt",ziptext);
}

slicesNumber && slice();
@@ -0,0 +1,2 @@
G28 Z
G1 Z30 F30
@@ -0,0 +1,71 @@
#Configuration file for printengine.pl to be called by SLAcer.js and other printer services
#Copyright 2016 Robert Koeppl, Fablab Leoben robert.koeppl@fablab-leoben.at
#http://www.fablab-leoben.at
#http://www.github.com/fablab-leoben
#released under the GPL v2
#this piece of software is provided with absolutely no warranty
#use at your own risk
log_file = "../log/printengine.log"
temporary_folder="./temp"
logging_enabled="TRUE"
#controllerboard="BBB"
controllerboard="raspiarduinoramps"
arduinotty="/dev/ttyACM0"
arduinottybaudrate="115200"
steps_per_mm="100"
#steps needed to move the Z-Axis 1mm
projector_type="Lightcrafter4500"
#default Light engine
projector_usb_device="/dev/ttyUSB0"
endstop_Z_max="TRUE"
endstop_Z_max_type="NC"
#NO="Normally Open", NC="Normally Closed". NC is preferred
endstop_Z_min="TRUE"
endstop_Z_min_type="NC"
#NO="Normally Open", NC="Normally Closed". NC is preferred
wiper="FALSE"
door_contact="TRUE"
#Defines if there is a door contact to determine if the enclosure is closed
X_pixels="912"
Y_pixels="1140"
Z_speed="5"
#mm/s
Z_max_speed="10"
#mm/s
Z_Autocal="True"
#Automatically determine Z-travel by triggering both endstops and dividing the Distance
overshoot="2"
#overshoot in mm to make sure the whole area is covered in resin correctly
testrun_capable="true"
#Capability to run testruns with wavelengthe that do not trigger polymerisation
testrun_color="RED"
#Color channel used for test run
prodrun_color="BLUE"
#Color Channel used for production run
vat_heatable="false"
vat_target_temperature=""
#Vat temperature in Celsius
check_vat_presence="false"
#board specific configuration for Beaglebone Black
virtual_terminal="1"
display_software="builtin"
#default is the builtin functionality support for other methods not implemented yet. fbi as other option planned next
display_device="/dev/fb0"
#PIN asignment
pin_zmin="testpin"
pin_zmax="testpin"
pin_wiper_min="testpin"
pin_wiper_max="testpin"
pin_door="testpin"
pin_step_Z="testpin"
pin_enable_Z="testpin"
pin_direction_Z="testpin"
pin_trigger_pre="testpin"
pin_trigger_post="testpin"
pin_enable_wiper="testpin"
pin_dir_wiper="testpin"
pin_step_wiper="testpin"
pin_vat_heater="testpin"
pin_vat_temperature="testpin"
pin_vat_presence="testpin"
#end of BBB specifics
@@ -0,0 +1,354 @@
#!/usr/bin/perl
#print engine to be called by SLAcer.js and other printer services orstandalone from command line
#Copyright 2016 Robert Koeppl, Fablab Leoben robert.koeppl@fablab-leoben.at
#http://www.fablab-leoben.at
#http://www.github.com/fablab-leoben
#released under the GPL v2
#this piece of software is provided with absolutely no warranty
#use at your own risk
#configuration is stored in printengine.cfg, do not use hardcoded configuration in ths perl script, that is bad practice.
#definition of libraries and modules to include
use warnings;
use strict;
use Getopt::Std;
use Getopt::Long;
use feature qw(say);
use Config::Simple;
use File::Which;
use Sys::Mmap;
use Graphics::Framebuffer;
use Time::HiRes;
use Archive::Zip;
use IO::File ;
use File::Spec::Functions qw(splitpath);
use File::Path qw(mkpath);
use File::Path 'rmtree';
use Device::SerialPort;
use Slurp;
#import configuration from configuration file
our $cfg = new Config::Simple();
$cfg->read("printengine.cfg");

#asign config values from config file to values in script
my $log_file = $cfg->param("log_file");
my $temporary_folder=$cfg->param("temporary_folder");
my $logging_enabled=$cfg->param("logging_enabled");
my $controllerboard=$cfg->param("controllerboard");
my $steps_per_mm=$cfg->param("steps_per_mm");
my $projector_type=$cfg->param("projector_type");
my $projector_usb_device=$cfg->param("projector_usb_device");
my $endstop_Z_max=$cfg->param("endstop_Z_max");
my $endstop_Z_max_type=$cfg->param("endstop_Z_max_type");
my $endstop_Z_min=$cfg->param("endstop_Z_min");
my $endstop_Z_min_type=$cfg->param("endstop_Z_min_type");
my $wiper=$cfg->param("wiper");
my $door_contact=$cfg->param("door_contact");
my $X_pixels=$cfg->param("X_pixels");
my $Y_pixels=$cfg->param("Y_pixels");
my $Z_speed=$cfg->param("Z_speed");
my $Z_max_speed=$cfg->param("Z_max_speed");
my $Z_Autocal=$cfg->param("Z_Autocal");
my $overshoot=$cfg->param("overshoot");
my $testrun_capable=$cfg->param("testrun_capable");
my $testrun_color=$cfg->param("testrun_color");
my $prodrun_color=$cfg->param("prodrun_color");
my $vat_heatable=$cfg->param("vat_heatable");
my $vat_target_temperature=$cfg->param("vat_target_temperature");
my $check_vat_presence=$cfg->param("check_vat_presence");
my $virtual_terminal=$cfg->param("virtual_terminal");
my $display_software=$cfg->param("display_software");
my $display_device=$cfg->param("display_device");
my $pin_zmin=$cfg->param("pin_zmin");
my $pin_zmax=$cfg->param("pin_zmax");
my $pin_door=$cfg->param("pin_door");
my $pin_step_Z=$cfg->param("pin_step_Z");
my $pin_enable_Z=$cfg->param("pin_enable_Z");
my $pin_direction_Z=$cfg->param("pin_direction_Z");
my $pin_trigger_pre=$cfg->param("pin_trigger_pre");
my $pin_trigger_post=$cfg->param("pin_trigger_post");
my $pin_enable_wiper=$cfg->param("pin_enable_wiper");
my $pin_dir_wiper=$cfg->param("pin_dir_wiper");
my $pin_step_wiper=$cfg->param("pin_step_wiper");
my $pin_wiper_max=$cfg->param("pin_wiper_max");
my $pin_wiper_min=$cfg->param("pin_wiper_min");
my $pin_vat_heater=$cfg->param("pin_vat_heater");
my $pin_vat_temperature=$cfg->param("pin_vat_temperature");
my $pin_vat_presence=$cfg->param("pin_vat_presence");
my $arduinotty=$cfg->param("arduinotty");
my $arduinottybaudrate=$cfg->param("arduinottybaudrate");
#asign additional variables
my $picturesarchive;
my $archivesource;
GetOptions("picturesarchive=s"=>\$picturesarchive, "archivesource=s"=>\$archivesource);#read pictures archive from command line option
my $layer_height;
my $exposure_time;
my $resin_settling_time;
my $cfg2;
#
#
#activate logging to logfile
if ($logging_enabled eq "TRUE")
{
unless (defined $log_file and length $log_file){
die "logging enabled but no logfile defined\n";}
open my $log_fh, ">", $log_file;
}
#basic sanity checks to determine whether or not the configuration is complete and makes at least some sense
#check if the parameters and pins needed for the features enabled are configured
unless (defined $steps_per_mm and length $steps_per_mm){
die "No steps per mm for Z Axis defined\n";}
unless (defined $overshoot and length $overshoot){
die "No overshoot for Z Axis defined\n";}
unless (defined $temporary_folder and length $temporary_folder){
die "No temporary folder defined\n";}
unless (defined $controllerboard and length $controllerboard){
die "No controllerboard defined\n";}
unless (defined $projector_type and length $projector_type){
die "No projector type defined\n";}
unless (defined $display_device and length $display_device){
die "No display device defined\n";}
unless (defined $X_pixels and length $X_pixels){
die "No pixels in X direction defined\n";}
unless (defined $Y_pixels and length $Y_pixels){
die "No pixels in Y direction defined\n";}
unless (defined $Z_speed and length $Z_speed){
die "No Z speed defined\n";}
unless (defined $Z_max_speed and length $Z_max_speed){
die "No Z max speed defined\n";}
unless (defined $prodrun_color and length $prodrun_color){
die "No production run color defined\n";}
if ($check_vat_presence eq "TRUE")
{
unless (defined $pin_vat_presence and length $pin_vat_presence )
{
die "Vat presence pin definition missing\n";}
}
if ($door_contact eq "TRUE")
{
unless (defined $pin_door and length $pin_door )
{
die "door pin not defined\n";}
}
if ($testrun_capable eq "TRUE")
{
unless (defined $testrun_color and length $testrun_color )
{
die "Z max endstops definition incomplete\n";}
}
if ($endstop_Z_max eq "TRUE")
{
unless (defined $endstop_Z_max_type and length $endstop_Z_max_type and
defined $pin_zmax and length $pin_zmax )
{
die "Z max endstops definition incomplete\n";}
}
if ($endstop_Z_min eq "TRUE")
{
unless (defined $endstop_Z_min_type and length $endstop_Z_min_type and
defined $pin_zmin and length $pin_zmin )
{
die "Z min endstops definition incomplete\n";}
}
if ($Z_Autocal eq "TRUE")
{
unless ($endstop_Z_max eq "TRUE" and $endstop_Z_min eq "TRUE" and
defined $endstop_Z_max_type and length $endstop_Z_max_type and
defined $pin_zmax and length $pin_zmax and
defined $endstop_Z_min_type and length $endstop_Z_min_type and
defined $pin_zmin and length $pin_zmin)
{
die "Z endstops definition incomplete for autotune of Z axis Length\n";}
}
if ($wiper eq "TRUE")
{
unless (defined $pin_enable_wiper and length $pin_enable_wiper and
defined $pin_step_wiper and length $pin_step_wiper and
defined $pin_dir_wiper and length $pin_dir_wiper and
defined $pin_zmin and length $pin_zmin and
defined $pin_wiper_max and length $pin_wiper_max and
defined $pin_wiper_min and length $pin_wiper_min
)
{
die "pin definition incomplete for wiper usage\n";}
}
if ($vat_heatable eq "TRUE")
{
unless (defined $vat_target_temperature and length $vat_target_temperature and
defined $pin_vat_heater and length $pin_vat_heater and
defined $pin_vat_temperature and length $pin_vat_temperature)
{
die "Vat temperature or heater parameters are configured incompletely\n";}
}

if ($controllerboard eq "BBB") #if the Board is set to be a Beagle Bone Black, we need to check if it actually is one
{
say "Beagle Bone Black selected, checking board type! - check command still missing";
unless (defined $pin_trigger_post and length $pin_trigger_post and defined $pin_trigger_pre and length $pin_trigger_pre){
die "trigger pin definition incomplete\n";}
}
elsif ($controllerboard eq "raspiarduinoramps"){
say "Raspberry PI with Arduino selected, checking board type! - check command still missing";
unless (defined $arduinotty and length $arduinotty and defined $arduinottybaudrate and length $arduinottybaudrate){
die "trigger pin definition incomplete\n";}
}
else {
say "unknown controller type $controllerboard , please review your configuration, get in touch with developers or fork the code on Github and contribute the code to use the new printer"
;
die "unknown board in configuration!\n";
}
if ($projector_type eq "Lightcrafter4500")
{
unless (defined $projector_usb_device and length $projector_usb_device){
die "No projector USB device defined\n";}
}
else {
say "unknown projector type $projector_type , please review your configuration, get in touch with developers or fork the code on Github and contribute the code to use the new printer"
;
die "unknown projector in configuration!\n";
}

if ($display_software eq "fbi") #ckeck for configured Software to send Pictures to the projector
{
my $display_software_path= which "fbi";
unless (defined $display_software_path and length $display_software_path){
die "configured display software not found\n";}
unless (defined $display_device and length $display_device){
die "display devicde not configured\n";}
unless (defined $virtual_terminal and length $virtual_terminal){
die "virtual terminal not configured\n";}
}
elsif ($display_software eq "builtin")
{
unless (defined $display_device and length $display_device){
die "display device not configured\n";}
}

else { #if the configured Display software matches none of the supported packages, die
say "unknown display software $display_software , please review your configuration, get in touch with developers or fork the code on Github and contribute the code to use the new printer"
;
die "unknown display software in configuration!\n";
}
#uncompresse archive to temporary folder
unless (defined $temporary_folder and length $temporary_folder){
die "No temporary folder defined\n";}
rmtree([ "$temporary_folder"]) or die "$!: for directory $temporary_folder\n";
unless (-d $temporary_folder) {
mkpath($temporary_folder) or die "Couldn't mkdir $temporary_folder: $!";}
my $port = Device::SerialPort->new($arduinotty);

# 19200, 81N on the USB ftdi driver
$port->baudrate($arduinottybaudrate);
$port->databits(8);
$port->parity("none");
$port->stopbits(1);

my $zip = Archive::Zip->new($picturesarchive);
$zip->extractTree('',$temporary_folder);



#read filelist from testfolder
my $dir = $temporary_folder;
if ($archivesource eq "slacer") {
$dir = "$temporary_folder/slices";
$cfg2 = new Config::Simple();
$cfg2->read("$temporary_folder/README.txt");
$layer_height=$cfg2->param("layer_height");
$exposure_time=$cfg2->param("exposure_time");
$resin_settling_time=$cfg2->param("resin_settling_time");}
else {
$dir = $temporary_folder;
}
opendir(DIR, $dir) or die $!;
my @pics
= grep {
m/\.png$/ # png files only
&& -f "$dir/$_" # and is a file
} readdir(DIR);
closedir(DIR);
#sort array
my @pics_sorted=sort { length $a <=> length $b||$a cmp $b } @pics;
say "layer_height=$layer_height µm, exposure_time=$exposure_time ms,resin_settling_time=$resin_settling_time ms\n";
my $exposure_time_us=1000*$exposure_time;#conversion to microseconds
my $resin_settling_time_us=1000*$resin_settling_time;#conversion to microseconds
say "layer_height=$layer_height µm, exposure_time=$exposure_time_us µs,resin_settling_time=$resin_settling_time_us µs\n";
sleep 10;
# Home Z-Axis
my @command_list=('G21','G28 Z');
send_commands(@command_list);
sleep 30;

my $z=0;
my $zdelta=$layer_height/1000;
#
#builtin framebuffer access

my $fb = Graphics::Framebuffer->new( FB_DEVICE=>$display_device, SPLASH=>0 );
$fb->clear_screen('OFF');
foreach(@pics_sorted){
#turn on LED -LED is mapped to the Fan, Fan Pin in Firmware has been set to a PWM pin.
my @command_list=('M106 S255');
send_commands(@command_list);
$fb->blit_write(
$fb->load_image(
{

'width' => $X_pixels, # Optional. Resizes to this maximum
# width. It fits the image to this
# size.

'height' => $Y_pixels, # Optional. Resizes to this maximum
# height. It fits the image to this
# size
'scale_type' => 'max',
'center' => $fb->{'CENTER_XY'},
'file' => "$dir/$_" # Usually needs full path
}
)
);
Time::HiRes::usleep("$exposure_time_us");
my @command_list=('M107');
send_commands(@command_list);
$fb->clear_screen('OFF');
$z=$z+$zdelta;
my $ztemp=$z+$overshoot;
my @command_list=("G1 Z $ztemp F $Z_speed","G1 Z $z F $Z_speed");
send_commands(@command_list);
my $zsleep=60*($zdelta+2*$overshoot)/$Z_speed*1000000; #microseconds, conversion from mm/min to mm/s
Time::HiRes::usleep("$zsleep");
Time::HiRes::usleep("$resin_settling_time_us");
}
#home Z axis to retrieve printed parts
my @command_list=('G28 Z');
send_commands(@command_list);

$fb->clear_screen('ON');
##sendcode- adapted and partially rewritten, inspiration taken from http://www.contraptor.org/about


sub send_commands{
my @command_list = @_;

#Open port


while (1) {
# Poll to see if any data is coming in
if ( my $char = $port->lookfor() ) {
$char =~ s/\r//;
print "$char\n";
if( $char =~ m/^(ok|start)$/){
#Send next command
my $next_command = shift @command_list;
print "$next_command\n";
$port->write("$next_command\n");
}else{
print "unknown: $char\n";
}
}
sleep 0.01;
unless(@command_list){last; }
}
}
###end sendcode
exit 0;
@@ -0,0 +1,47 @@
#!/usr/bin/perl
use Device::SerialPort;
use Time::HiRes qw/sleep/;
use Slurp;

#Slup each file into a command list
my @command_list;
for my $file ( @ARGV ){
push @command_list, split('\n',slurp $file);
}

#If your board autoresets when talked to ( like a Sanguino ), you can uncomment the line bellow to get the machine to home position before sending the actual gcode
#send_commands('G21','G91','G1 X-150 Y-150','G1 X-150 Y-150','G1 X-150 Y-150','G1 X-150 Y-150');

send_commands(@command_list);

sub send_commands{
my @command_list = @_;

#Open port
my $port = Device::SerialPort->new("/dev/ttyACM0");

# 19200, 81N on the USB ftdi driver
$port->baudrate(115200);
$port->databits(8);
$port->parity("none");
$port->stopbits(1);

while (1) {
# Poll to see if any data is coming in
if ( my $char = $port->lookfor() ) {
$char =~ s/\r//;
print "$char\n";
if( $char =~ m/^(ok|start)$/){
#Send next command
my $next_command = shift @command_list;
print "$next_command\n";
$port->write("$next_command\n");
}else{
print "unknown: $char\n";
}
}
sleep 0.01;
unless(@command_list){last; }
}
}

No commit comments for this range

You can’t perform that action at this time.