From 688d2450d0b9ebf59206978ef23b14e9ea642457 Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Tue, 27 Dec 2011 21:05:50 +0100 Subject: [PATCH] Perl Lasic driver - basic module, PBM renderer and two example scripts. Untested with real hardware yet. --- perl/Brm/Lasic.pm | 179 ++++++++++++++++++++++++++++++++++++++++++ perl/Brm/Lasic/PBM.pm | 104 ++++++++++++++++++++++++ perl/box.pl | 22 ++++++ perl/render.pl | 16 ++++ 4 files changed, 321 insertions(+) create mode 100644 perl/Brm/Lasic.pm create mode 100644 perl/Brm/Lasic/PBM.pm create mode 100755 perl/box.pl create mode 100755 perl/render.pl diff --git a/perl/Brm/Lasic.pm b/perl/Brm/Lasic.pm new file mode 100644 index 0000000..f936e59 --- /dev/null +++ b/perl/Brm/Lasic.pm @@ -0,0 +1,179 @@ +package Brm::Lasic; + +=head1 NAME + +Brm::Lasic - interface for the brmlab lasercutter + +=head1 SYNOPSIS + +use Brm::Lasic; + + $lasic = Brm::Lasic->new(dev => '/dev/ttyUSB0'); + $lasic->reset(); + $lasic->focus(-3); + $lasic->laser_on(); + $lasic->move(40, 20); + $lasic->move(80, 0); + $lasic->laser_off(); + +=cut + +use Moose; +use Device::SerialPort; + +use warnings; +use strict; + +our $VERSION = '0.1'; +$VERSION = eval $VERSION; + +=head1 DESCRIPTION + +Brm::Lasic instance represents a laser cutter. +You can directly use the basic functions like moving the laser, +turning the laser on/off etc. +Further add-ons provide extended functionality +like rendering a picture. + +=head2 ATTRIBUTES + +=over 4 + +=item B + +Name with the tty device associated with Lasic serial port. +=cut +has 'dev' => (is => 'ro', isa => 'Str', required => 1); + +=item B + +The tty device object. Avoid using directly. +=cut +has 'port' => (is => 'rw', isa => 'Device::SerialPort'); + +=item B + +The tty device filehandle. Avoid using directly. +=cut +has 'fd' => (is => 'rw', isa => 'Device::SerialPort'); + +=back + +=head2 METHODS + +=over 4 + +=item B(dev => tty device name) + +The dev attribute must be specified. +=cut + +sub BUILD { + my $self = shift; + + use Symbol qw(gensym); + my $fd = gensym(); + my $port = tie(*$fd, "Device::SerialPort", $self->dev()); + $port or die $self->dev().": $!"; + $self->port($port); + $self->fd($fd); + + $self->port->datatype('raw'); + $self->port->baudrate(115200); + $self->port->databits(8); + $self->port->parity("none"); + $self->port->stopbits(1); + $self->port->handshake("none"); + $self->port->write_settings(); +} + +=item B + +Reset the laser cutter. This makes the cutter re-calibrate itself +in both axes and then moves to the (0, 0) position. +=cut + +sub reset { + my $self = shift; + $self->msg('s', 1); +} + +=item B($steps) + +Adjust focus. $steps (positive for down, negative for up) +denotes the number of focus adjustment steps. +=cut + +sub focus { + my $self = shift; + my ($steps) = @_; + if ($steps > 0) { + $self->msg('s', 3) for (1..$steps); + } else { + $self->msg('s', 2) for (1..-$steps); + } +} + +=item B + +Turn on the laser (to etching intensity). +=cut + +sub laser_on { + my $self = shift; + $self->msg('l', 254); +} + +=item B + +Turn off the laser (to navigation intensity). +=cut + +sub laser_off { + my $self = shift; + $self->msg('l', 0); +} + +=item B($x, $y) + +=item B($x, $y, $speed) + +Move the laser to given coordinates. +If $speed is not specified (recommended), a reasonable default is used. +=cut + +sub move { + my $self = shift; + my ($x, $y, $speed) = @_; + defined $speed or $speed = 20; + $self->msg('v', $speed, $x, $y); +} + +=item B(...) + +Send a message to the serial port and wait for its completion. +=cut + +sub msg { + my $self = shift; + + my (@args) = @_; + push @args, 1; + + my $fd = $self->fd(); + print $fd join(' ', @args)."\r\n"; + my $msg = <$fd>; + chomp $msg; + print "(rep: $msg)\n"; +} + +=back + +=head1 COPYRIGHT + +(c) 2011 Petr Baudis Epasky@ucw.czE. +This module may be redistributed using the same terms as Perl itself. + +=cut + +1; diff --git a/perl/Brm/Lasic/PBM.pm b/perl/Brm/Lasic/PBM.pm new file mode 100644 index 0000000..cc13f0a --- /dev/null +++ b/perl/Brm/Lasic/PBM.pm @@ -0,0 +1,104 @@ +package Brm::Lasic::PBM; + +=head1 NAME + +Brm::Lasic::PBM - Render PBM using Brm::Lasic + +=head1 SYNOPSIS + +use Brm::Lasic::PBM; + + my $lasic = Brm::Lasic->new(dev => '/dev/ttyUSB0'); + $lasic->reset(); + my $pbm = Brm::Lasic::PBM(lasic => $lasic, file => 'brm.pbm'); + $pbm->render(); + +=cut + +use Moose; + +use warnings; +use strict; + +our $VERSION = '0.1'; +$VERSION = eval $VERSION; + +=head1 DESCRIPTION + +Render a bitmap picture from PBM file using Brm::Lasic lasercutter. + +=head2 ATTRIBUTES + +=over 4 + +=item B + +Lasercutter instance. +=cut +#has 'lasic' => (is => 'ro', isa => 'Brm::Lasic', required => 1); + +=item B + +Filename of the picture. +=cut +has 'file' => (is => 'ro', isa => 'Str', required => 1); + +=item B + +Length of etching per pixel in milliseconds; +a reasonable default is provided but this depends on the material. +=cut +has 'pixeltime' => (is => 'ro', isa => 'Num', default => 200, required => 1); + +=back + +=head2 METHODS + +=over 4 + +=item B(lasic => Brm::Lasic, file => bitmap filename) +=item B(lasic => Brm::Lasic, file => bitmap filename, pixeltime => ms) + +The lasic and file attributes must be specified. + +=item B + +Engrave the image on the laser cutter. +=cut + +sub render { + my $self = shift; + my ($w, $h, @bitmap); + + open my $fd, $self->file or die $self->file.": $!"; + # Two silly lines. + <$fd>; <$fd>; + my $dim = <$fd>; chomp $dim; + ($w, $h) = split(/ /, $dim); + my @bits = <$fd>; chomp @bits; + @bitmap = map { split('', $_) } @bits; + close $fd; + + for my $y (0..$h-1) { + for my $x (0..$w-1) { + my $bit = $bitmap[$y * $h + $x]; + $bit or next; + $self->lasic->move($x, $y); + $self->lasic->laser_on(); + use Time::HiRes; + Time::HiRes::usleep($self->pixeltime * 1000); + $self->lasic->laser_off(); + } + } +} + +=back + +=head1 COPYRIGHT + +(c) 2011 Petr Baudis Epasky@ucw.czE. +This module may be redistributed using the same terms as Perl itself. + +=cut + +1; diff --git a/perl/box.pl b/perl/box.pl new file mode 100755 index 0000000..d91c39f --- /dev/null +++ b/perl/box.pl @@ -0,0 +1,22 @@ +#!/usr/bin/perl +# +# Simple Brm::Lasic example - draw a 100x100 rectangle. + +use warnings; +use strict; + +use lib qw(.); +use Brm::Lasic; + +my $lasic = Brm::Lasic->new(dev => '/dev/ttyUSB0'); +$lasic->reset(); + +$lasic->focus(-2); +$lasic->focus(2); + +$lasic->laser_on(); +$lasic->move(100, 0); +$lasic->move(0, 100); +$lasic->move(-100, 0); +$lasic->move(0, -100); +$lasic->laser_off(); diff --git a/perl/render.pl b/perl/render.pl new file mode 100755 index 0000000..c72147f --- /dev/null +++ b/perl/render.pl @@ -0,0 +1,16 @@ +#!/usr/bin/perl +# +# Render a PBM image using Brm::Lasic - pass it as a parameter! + +use warnings; +use strict; + +use lib qw(.); +use Brm::Lasic; +use Brm::Lasic::PBM; + +my $lasic = Brm::Lasic->new(dev => '/dev/ttyUSB0'); +$lasic->reset(); + +my $pbm = Brm::Lasic::PBM->new(lasic => $lasic, file => $ARGV[0]); +$pbm->render();