You are reading a single comment by @Gordon and its replies. Click here to read the full conversation.
  • A bit of an update to this... I bought this laser module, which contains a driver IC: http://www.amazon.com/dp/B00HHHVV2K/ref=pe_385040_30332200_TE_item

    It's a bit pricey (£100), but I thought that if I was going to do it then I might as well do it properly!

    I then connected an Espruino up to an old Plotmate A3M plotter that I had hanging around. These are just dumb plotters - internally there's the mechanics, a power supply, drive transistors, and some circuitry that appears to serve no useful purpose apart from to make it difficult to use.

    The connections on the back are easy. There's a 20 pin connector, and all of one side of it is ground. On the other side there's:

    Pin 1,2,3,4 - X stepper
    Pin 5,6,7,8 - Y stepper
    Pin 9 - Pen down (inverted)
    Pin 10 - Axis end stop hit (inverted)
    

    I connected these right down the side of the Espruino board (B13,B14,B15,C4,C5,C6,C7,C8,C9,C10).

    After a huge amount of messing around, I found out the following on how the steppers are driven:

    motorx = [B13,B14,B15,C4] (0,1,2,3)
    Pin 1 (common) -> 4 (coil A), 5 (coil a)
    Pin 2 (common) -> 3 (coil B), 6 (coil b)
    
    
    1324
    AaBb
    0 -> 0110
    1 -> 0101
    2 -> 0100
    3 -> 0101
    
    4 -> 1010
    5 -> 1001
    6 -> 1000
    7 -> 1001
    
    8 -> 0010
    9 -> 0001
    10 -> 0000
    11 -> 0001
    
    12 -> 1010
    13 -> 1001
    14 -> 1000
    15 -> 1001
    
    step order = [14,13,9,3,2,0,8,4]
    
    
    motory = [C5,C6,C7,C8] (4,5,6,7)
    Pin 1 (common) -> 5 (coil A),6 (coil a)
    Pin 2 (common) -> 3 (coil B),4 (coil b)
    
    1324
    AaBb
    
    0 -> 1010
    1 -> 0010
    2 -> 1001
    3 -> 0001
    
    4 -> 0110
    5 -> 0110
    6 -> 0101
    7 -> 0101
    
    8 -> 1000
    9 -> 0000
    10 -> 1001
    11 -> 0001
    
    12 -> 0100
    13 -> 0100
    14 -> 0101
    15 -> 0101
    
    step order = [8,0,1,4,12,14,3,10];
    

    And finally: here's the code so far that's needed to drive the plotter - it'll home the axes, and draw a circle...

    var pins = [B13,B14,B15,C4,C5,C6,C7,C8,C9,C10];
    var ENDSTOP = pins[9]; // negated
    // pins[8] = !pen down
    // pins[9] = !axis hit
    var motorx = pins.slice(0,4);
    var xsteps = [14,13,9,3,2,0,8,4];
    var motory = pins.slice(4,8);
    var ysteps = [8,0,1,4,12,14,3,10];
    var motorxoff = 10;
    var motoryoff = 9;
    
    
    function Stepper(pins, pattern, offpattern) {
      this.pins = pins;
      this.pattern = pattern;
      this.offpattern = offpattern;
      this.pos = 0;
    }
    
    Stepper.prototype.setHome = function() {
      this.pos = 0;
    };
    
    Stepper.prototype.stop = function(turnOff) {
      if (this.interval) {
        clearInterval(this.interval);
        this.interval = undefined;
      }
      if (turnOff && this.offpattern)
        digitalWrite(this.pins, this.offpattern);
    };
    
    Stepper.prototype.moveTo = function(pos, milliseconds, callback, turnOff) {
      pos = 0|pos; // to int
      if (milliseconds===undefined)
        milliseconds = Math.abs(pos-this.pos)*10;
      this.stop(turnOff);
      if (pos != this.pos) {
        var stepper = this;
        this.interval = setInterval(function() {
          // remove interval if needed
          if (stepper.pos == pos) {
            stepper.stop(turnOff);
            if (callback)
              callback();
          } else {
            // move onwards
            stepper.pos += (pos < stepper.pos) ? -1 : 1;
            // now do step
            digitalWrite(stepper.pins, stepper.pattern[ stepper.pos & (stepper.pattern.length-1) ]);
          }
        }, milliseconds / Math.abs(pos-this.pos));
      } else {
        if (callback)
          setTimeout(callback, milliseconds);
      }
    };
    
    var x = new Stepper(motorx, xsteps, motorxoff);
    var y = new Stepper(motory, ysteps, motoryoff);
    
    function home(callback) {
      x.moveTo(50,undefined,function() {
        y.moveTo(50,undefined,function() {
          setWatch(function() {
            y.stop();
            y.setHome();
            y.moveTo(50,undefined,function() {
              setWatch(function() {
                x.stop();
                x.setHome();
                y.moveTo(0,undefined,callback,true);
              }, ENDSTOP, {edge:falling, repeat:false});
              x.moveTo(-10000);
          });
          }, ENDSTOP, {edge:falling, repeat:false});
          y.moveTo(-10000);
        });
      });
    }
    
    function setPenDown(down) {
      digitalWrite(pins[8], !down);
    }
    
    function draw(positions, callback) {
      function moveTo(p, callback) {
        var dx = x.pos - p[0];
        var dy = y.pos - p[1];
        var d = Math.sqrt(dx*dx+dy*dy);
        var time = d*50; // speed
        x.moveTo(p[0],time, undefined, false);
        y.moveTo(p[1],time, callback, false);
      }
      function moveToNext() {
        print(positions.length);
        if (positions.length) {
          moveTo(positions.shift(), moveToNext);
        } else {
          setPenDown(false);
          x.stop(true);
          y.stop(true);
          callback();
        }
      }
      
      if (positions.length) {
        moveTo(positions.shift(), function() {
          setPenDown(true);
          moveToNext();
        });
      } else {
        callback();
      }
    }
    
    function circle() {
      var positions = [];
      for (var i=0;i<20;i++) {
        var t = Math.PI*2*i/20;
        positions.push([(1+Math.cos(t))*200,(1+Math.sin(t))*200]);
      }
      draw(positions, function() {
        print("done");
      }); 
    }
    
    

    The laser is currently attached to a large aluminium heatsink, and then to the pen carriage. Hopefully I'll make laser control automatic soon, but for now it's done manually. It kind of works...


    1 Attachment

    • 20140612_123814_sml.jpg
About

Avatar for Gordon @Gordon started