Top Banner

of 20

3D Printer Do-over

Oct 11, 2015

Download

Documents

WarungElektro
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
  • Hobby blog about tech tips I've picked up, projects I'm working on, or links to useful information andcool stuff. I'm an Electrical Engineer and professional Analog IC designer for 25 years playing in myspare time. Arduino, hacking consumer electronics, video game hardware, satellite TV, PC building,Android apps, appliance repairs and whatever else that interests me.

    Arduino XYZ CNC / 3D Printer Do-over

    Now that I've polished my Java skills over the past couple years I wanted to come back andimprove a previous project of an XYZ CNC machine that was controlled by Arduinos and acrude PC Java program.

    This is the hardware I'm using. I've covered how to build all these pieces in earlier blogposts. As I work through the pieces I'll refresh the info on the hardware and sketches.

    I'll need to make some software updates to the Arduinos, but the original Arduino sketchesare posted on my download pages. I want to improve the handshaking, auto detect thearduinos, and process HPGL files better, plus make a better GUI.

    There are three Arduinos. The first is the XYZ motor controller that uses two motor shieldsfrom ADAfruit. I posted a hack on how to attach two to the same Arduino. I also replacedthe motor driver chips with some higher capacity chips and put on heat sinks. The reasonone arduino does all this work is I absolutely want to synchronize the x, y and z moves. Idon't want to risk dropping a move or mistiming a move due to USB communication glitches. This arduino gets HPGL format commands that give position from and to commands and itcalculates all the sub stepping to get there.

    The second arduino only controls the speed and direction of the cutter. The cutter is acordless drill motor and chuck controlled by some heavy duty MOSFET switches.

    The third arduino is connected to position encoders and an LCD. It reads back the positionand also displays it and any other messages the machine has to say. This is mostly used as

    Siliconfish: Arduino XYZ CNC / 3D Printer Do-over http://blog.workingsi.com/2013/02/arduino-xyz-cnc-3d-printer-pc-softwa...

    1 of 20 8/16/2014 10:17 PM

  • a watchdog, since the steppers count position. If the position gets off from what the machinethinks it should be I should stop and let the user figure things out.

    Power is supplied by a old PC desktop power supply.

    My PC original control program was very crude and didn't work if the Arduinos were indifferent COM ports and didn't have file spooling capability. I'm way better at coding now,that was my very first program after "Hello World".

    So my project this time is to write a respectable java program that will work for everyone, Itwill read/spool in a standard HPGL command file and control the CNC. It will also havebuttons for manual controlling the CNC.

    I'm using Java and the netbeans development environment, which is free from oracle.I'm starting with the basic Java serial tool I just wrote for the PC that will communicate withthe Arduinos.

    http://blog.workingsi.com/2013/01/revisiting-arduino-control-from-pc.html

    The first piece will be a startup routine that finds all three Arduinos and establishes a link. Each arduino sketch will be updated to send an initialization sequence I can look for.

    After that there will be a choice of entering manual mode to push buttons on the GUI tomove, or load an HPGL drawing file. There should be a routine for setting the home position.

    First I'm going to work on communicating with the position sensor I described in this post:http://blog.workingsi.com/2011/02/position-sensor-for-arduino-xyz-cnc.htmlI fired it up with the serial tool and the original code in the post is working fine, the encoder isconstantly spitting out the position on the COM port as fast as it can. For now I shouldn'tneed to alter the Arduino sketch. My PC program will have to seek and identify this datastream and map it properly.

    Next I fired up the XYZ stepper Arduino and that seems to be in good order as well. Theoriginal sketch was built from this post. You need to use the custom library to use all foursteppershttp://blog.workingsi.com/2011/03/method-for-controlling-4-steppers-from.htmland the sketch for the XYZ control is posted on my download site:http://code.google.com/p/arduino-java-xyzcnc/downloads/detail?name=XYZ_CNC_HPGL_r13.pde&can=2&q=#makechanges

    Writing the Java to connect to all the Arduinos

    First step is to perfect the serial port autodetection. I'll use the touchport command and thenlook for a unique broadcast from each Arduino in order to assign them to ports.

    After a long stall, I finally got this working in a recent project.http://blog.workingsi.com/2013/07/lcd-system-monitor-for-pc-case-bling.html

    I had been hung up from a mistake. I used touchPort, to get the port names, and theninstantiated a serial class to talk to each one. However that process wiped out my list ofports so the loop failed. Also I learned I have to wait and let the listener have time to heareach Arduino before moving on. Here are the basic pieces.

    Siliconfish: Arduino XYZ CNC / 3D Printer Do-over http://blog.workingsi.com/2013/02/arduino-xyz-cnc-3d-printer-pc-softwa...

    2 of 20 8/16/2014 10:17 PM

  • This Java loop goes through all the ports: int iii=0;

    while (clientPortName.equals("")) {

    //scan for devices and list

    serial.touchPort("", Integer.valueOf(serialRates.getSelectedItem().toString()));

    jListPorts.setModel(new javax.swing.AbstractListModel() {

    String[] strings = serial.portNames;

    public int getSize() { return strings.length; }

    public Object getElementAt(int i) { return strings[i]; }

    });

    if (!serial.portNames[iii].equals("")) {

    System.out.println("PORT:" + serial.portNames[iii]);

    setupCom(serial.portNames[iii]);

    // give it some time to hear the Arduino calling

    long currentTimeMillis = System.currentTimeMillis();

    while (System.currentTimeMillis()19) {

    System.out.println("Exiting, Arduino not found");

    System.exit(1);

    }

    }

    This routine below grabs each port and sets up a listener and sets a flag that breaks the loopabove if the desired character is found.

    public void setupCom(final String portName) throws SerialException{

    //System.out.println(">>"+portName);

    serial.dispose();

    serial = new Serial(portName, Integer.valueOf(serialRates.getSelectedItem().toString()), 'E', 8, 2 );

    //Add the listener to pipe remote responses

    serial.addSerialEventListener(new Listener_SerialEvent() {

    @Override

    public void SerialEventOccurred(int message) {

    String message_out = formatRead(message);

    if (message_out.equalsIgnoreCase("Q")) {

    System.out.println(portName + " detected Q - gotcha!!!");

    clientPortName = portName;

    send("Hello World!"); //respond so Arduino stops sending Q

    }

    }

    });

    }

    I don't have to break the upper loop, I could go back and set up the port at the end of looping,but this is faster if I stop when the right port is found.

    I've updated the serial Arduino tool with a field for the character is it going to look for toconnect. In this picture the GUI has three Arduinos connected. One is transmitting Z, one isbusy, and one is transmitting A. The one transmitting Z , COM4, is grabbed and now sendand receive can begin.

    Siliconfish: Arduino XYZ CNC / 3D Printer Do-over http://blog.workingsi.com/2013/02/arduino-xyz-cnc-3d-printer-pc-softwa...

    3 of 20 8/16/2014 10:17 PM

  • Download the executable here:https://code.google.com/p/arduino-java-xyzcnc/downloads/detail?name=SifishSerialArdunioTool.jar&can=2&q=

    Now I will use multiple of these tools to search and connect to the three Arduinos.I've got that code working, each Arduino is set to broadcast a different character to be foundby the serial comm port scanner. However that means I had to resurrect the old arduinocode and modify it.

    I had no trouble with the encoder program https://code.google.com/p/arduino-java-xyzcnc/downloads/list, the rotary encoder sketch. I was able to add the establishContact() functionfrom the Arduino serial response example.

    The XYZ motor controller program is broken. The old AFMotor.h libraries I had been usingfrom Adafruit don't seem to be working, they don't compile in the new release. I updatednew library from here:http://learn.adafruit.com/adafruit-motor-shield/downloadsthat library seems OK, but my modified AFMotorA.h library for use in stacking shields isbroken. maybe I need to remake it.

    The big problem turned out to be that now Arduino installs to the Program Files (x86)directory, which is read only and blocked by default. I had to make all the library filesunblocked by right clicking and selecting properties. In the process I did remake theAFMotorA library. All I did was search and replace AFMotor for AFMotorA and AF_Stepperwith AF_StepperA, and microsteppercurve to microsteppercurveA in the .cpp, .h andkeywords files. Also rename the files AFMotorA.cpp and AFMotorA.h. Now the old sketchcompiles pointing to the AFMotor libraries.

    I'm using three instances of my serial tool with only slight modification. One for each arduino.Had to do some mundane coding to pass the serial responses up to the main Arduino GUI byadding listeners to each of the serial port GUIs and passing them up to the main GUI.

    The connection process takes so long that I want to move it into a thread by itself rather thanlocking up the GUI for 15 seconds. that fixed a lot of weird problems I was having with theGUI not drawing, messages not scrolling etc.

    Cool, now I have a main GUI that when you press connect, runs out and finds 3 differentArduinos and scrolls a log of what it is doing. This simple task had eluded me for a whiledue to stupid mistakes.

    Siliconfish: Arduino XYZ CNC / 3D Printer Do-over http://blog.workingsi.com/2013/02/arduino-xyz-cnc-3d-printer-pc-softwa...

    4 of 20 8/16/2014 10:17 PM

  • Now the fun part, re-writing the code to actually move the XYZ machine.

    Cleaning up the Arduino Encoder Program & Sketch

    Updated the code to pull the position from the Arduino, parse the string and display it. I'mfinding the response time from the Arduino is really slow between when the encoders andLCD report the change, and when the string shows up on the serial bus. I'm going to changethe encoder code to only print to serial when there is a change to reduce the traffic andhopefully prevent the backlog. It worked! Now I only send serial traffic when there is achange, and response is much faster.

    Realized I need a function for the Encoder program to tell it to reset it's counters. That is fora Home position command. Added that and updated the position encoder program. Alsofound a bug that the position counters were unsigned integers!! The LCD calculationseemed right but the serial information signs were mixed up. Fixed it. It is working muchbetter now!

    /* Rotary encoder readout for XYZ CNC machine */

    // Encoders connected as follows

    // X encoder PIN A - Analog 0

    // X encoder PIN B - Analog 1

    // Y encoder PIN A - Analog 2

    // Y encoder PIN B - Analog 3

    // Z encoder PIN A - Analog 4

    // Z encoder PIN B - Analog 5

    // Pin C of all encoders is grounded, center pin of http://www.sparkfun.com/products/9117

    // thus variable PINC will read this entire register simultaneously

    // this avoids missing states of the encoder

    //Based on

    //http://www.circuitsathome.com/mcu/reading-rotary-encoder-on-arduino

    //Expanded to 3 encoders and written to be more clear and less over elegant

    //Variables to set the counts/inch

    Siliconfish: Arduino XYZ CNC / 3D Printer Do-over http://blog.workingsi.com/2013/02/arduino-xyz-cnc-3d-printer-pc-softwa...

    5 of 20 8/16/2014 10:17 PM

  • #define TH_PER_IN 20 //lead screw threads per inch

    #define CT_PER_REV 48 //encoder counts per revolution

    // Thus the accuracy of the measurement 1 inch /(TH_PER_IN*CT_PER_REV)

    //Variable to reverse the sign if the machine and encoder don't agree with your sense of things

    // set to 1 or -1

    #define REFLECTX -1

    #define REFLECTY -1

    #define REFLECTZ 1

    #include

    LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

    unsigned int olddata;

    unsigned int newdata;

    char newX;

    char newY;

    char newZ;

    char oldX;

    char oldY;

    char oldZ;

    long signed int counterX = 0;

    long signed int counterY = 0;

    long signed int counterZ = 0;

    char inByte = 0; // incoming serial byte

    // table of meaning of states, input is two bits old value, two bits new value

    // the encoder has either moved +1, -1 or stayed in the same place

    int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};

    void setup()

    {

    /* Setup encoder pins as inputs */

    // http://www.arduino.cc/en/Reference/PortManipulation

    DDRC = B00000000; //Sets input direction all to analog inputs

    PORTC = B11111111; //Sets pull ups on the analog pins to 1

    Serial.begin (9600);

    establishContact();

    Serial.println("Encoders Found");

    counterX = 0;

    counterY = 0;

    counterZ = 0;

    pinMode(13 ,OUTPUT); //turn on backlight

    digitalWrite(13, HIGH); //turn on backlight

    lcd.begin(20,4);

    delay(500); //Optrex display needs to rest after a begin

    lcd.clear();

    lcd.setCursor(0,0);

    delay(100); //Optrex display needs to rest after setting cursor

    lcd.print("XYZ CNC Position");

    lcd.setCursor(0,1);

    lcd.print("X: ");

    lcd.setCursor(0,2);

    lcd.print("Y: ");

    lcd.setCursor(0,3);

    lcd.print("Z: ");

    //send initial position

    Serial.print(1000*counterX/(TH_PER_IN*CT_PER_REV*REFLECTX), DEC); Serial.print(":");

    Serial.print(1000*counterY/(TH_PER_IN*CT_PER_REV*REFLECTY), DEC); Serial.print(":");

    Serial.print(1000*counterZ/(TH_PER_IN*CT_PER_REV*REFLECTZ), DEC);

    Serial.println(";");

    Siliconfish: Arduino XYZ CNC / 3D Printer Do-over http://blog.workingsi.com/2013/02/arduino-xyz-cnc-3d-printer-pc-softwa...

    6 of 20 8/16/2014 10:17 PM

  • }void loop()

    {

    //This loop needs to run fast to avoid missing encoder states

    newdata = PINC;

    if( newdata != olddata ) {

    newX = newdata & 0x03; //mask out just the X bits

    oldX = olddata & 0x03; //mask out just the X bits

    oldX = oldX > 2; //shift to LSBs

    oldY = olddata & 0x0C; //mask out just the Y bits

    counterY += enc_states[oldY + newY] ;

    newZ = newdata & 0x30; //mask out just the Z bits

    newZ = newZ >> 4; //shift to LSBs

    oldZ = olddata & 0x30; //mask out just the Z bits

    oldZ = oldZ >> 2; //shift to form address to table

    counterZ += enc_states[oldZ + newZ] ;

    // only send updates over serial bus when data has changed to reduce traffic

    Serial.print(1000*counterX/(TH_PER_IN*CT_PER_REV*REFLECTX), DEC); Serial.print(":");

    Serial.print(1000*counterY/(TH_PER_IN*CT_PER_REV*REFLECTY), DEC); Serial.print(":");

    Serial.print(1000*counterZ/(TH_PER_IN*CT_PER_REV*REFLECTZ), DEC);

    Serial.println(";");

    } else {

    // only update the display when the data is NOT changing, this speeds up polling

    lcd.setCursor(3,1);

    lcd.print(1000*counterX/(TH_PER_IN*CT_PER_REV*REFLECTX), DEC);

    lcd.print(" mils ");

    lcd.setCursor(3,2);

    lcd.print(1000*counterY/(TH_PER_IN*CT_PER_REV*REFLECTY), DEC);

    lcd.print(" mils ");

    lcd.setCursor(3,3);

    lcd.print(1000*counterZ/(TH_PER_IN*CT_PER_REV*REFLECTZ), DEC);

    lcd.print(" mils ");

    // check if any serial messages have come in, since not busy

    if (Serial.available() > 0) {

    // get incoming byte:

    inByte = Serial.read();

    // reset position on indicated counter

    if (inByte == 'X') counterX = 0;

    if (inByte == 'Y') counterY = 0;

    if (inByte == 'Z') counterZ = 0;

    if (inByte == '@' ) {

    counterX = 0; counterY = 0; counterZ = 0;

    }

    // any other serial traffic respond with current position

    Serial.print(1000*counterX/(TH_PER_IN*CT_PER_REV*REFLECTX), DEC); Serial.print(":");

    Serial.print(1000*counterY/(TH_PER_IN*CT_PER_REV*REFLECTY), DEC); Serial.print(":");

    Serial.print(1000*counterZ/(TH_PER_IN*CT_PER_REV*REFLECTZ), DEC);

    Serial.println(";");

    }

    }

    olddata = newdata;

    Siliconfish: Arduino XYZ CNC / 3D Printer Do-over http://blog.workingsi.com/2013/02/arduino-xyz-cnc-3d-printer-pc-softwa...

    7 of 20 8/16/2014 10:17 PM

  • } void establishContact() {

    while (Serial.available()

  • is to have the PC software do the hard work, and only send specific movement commands tothe Arduino. The Arduino will still linear interpolation to move the X and Y motors together tomake smooth diagonals. I don't think it's necessary to do linear interpolation with the Z axis.

    New Arduino XYZTool code

    Java program will need to send the following commands to the Arduino.Semicolon indicates command termination and begin executing.Command set proposed:

    R; = Reset position counters to 0:0:0 (Set Home)

    C; = Coordinates: Report back the current stepper counter position over theserial link for use in calibrating and catching errors

    Pn; = Z axis relative move n steps

    Zn; = Move to absolute Z coord

    Mx:y; = Move relative by x:y steps

    Ax:y; = Move to absolute coordinate x:y

    Tn; = Set tool speed to n. May be positive or minus. 0 is off.

    S; = Stop all motors

    I; = power on/initialize motors

    After each command the Arduino will send back characters:

    B; - Arduino received the command and is busy executing it

    R; - Ready for a new command

    Cx:y:z - Arduino counters say this is the current coordinates

    I added each of these commands to the buttons in the Java program. Now I need to jumpback to the Arduino to interpret them.

    The Adafruit v2 motor shields came in the mail. I assembled them exactly like the tutorial. Istacked two shields, and shorted the address bit on the bottom one. One for XY and one forZ and tool. http://learn.adafruit.com/adafruit-motor-shield-v2-for-arduino/stacking-shieldsI hooked up a tiny DC motor and three hobby steppers to the shields for a mock up to usewhile I write the code, without worrying about running the motors into a wall, etc.A basic motor party script with both shields worked right off the bat.

    Now I'm rewriting the motor control program for the Arduino to interpret the simplecommands from the Java GUI, rather than try to decode HPGL all by itself. That was limitingthe functions I could perform. It didn't take as long as I thought it would, because I was ableto reuse the heavy lifting from the old program and just change the command interpretation

    Siliconfish: Arduino XYZ CNC / 3D Printer Do-over http://blog.workingsi.com/2013/02/arduino-xyz-cnc-3d-printer-pc-softwa...

    9 of 20 8/16/2014 10:17 PM

  • loops. I still need to add the timeout and error catching stuff but it's working pretty wellalready!

    Arduino sketch for XYZ CNC control:/*

    Program to intepret CNC commands and activate motors

    Uses Adafruit v2 motor shields http://learn.adafruit.com/adafruit-motor-shield-v2-for-arduino/overview

    Commands that will be received:

    R; = Reset position counters to 0:0:0 (Set Home)

    C; = Coordinates: Report back the current stepper counter position over the serial link for use in calibrating and catching errors

    Pn; = Z axis relative move n steps

    Zn; = Move to absolute Z coord

    Mx:y; = Move relative by x:y steps

    Ax:y; = Move to absolute coordinate x:y

    Tn; = Set tool speed to n. May be positive or minus. 0 is off.

    S; = Stop all motors

    I; = Power all motors/ initialize

    After each command the Arduino will send back characters:

    B; - Arduino received the command and is busy executing it

    R; - Ready for a new command

    Cx:y:z - Arduino counters say this is the current coordinates

    */

    #define INCH 4000 //steps per inch of the machine = threads per inch * steps per rotation

    #define RPM 30 //speed of the stepper motors

    #include

    #include

    //#include "utility/Adafruit_PWMServoDriver.h"

    // Create the motor shield object with the default I2C address for Z axis stepper and Tool

    Adafruit_MotorShield AFMS_ZT = Adafruit_MotorShield();

    // Or, create it with a different I2C address for stacking for X and Y axis steppers

    Adafruit_MotorShield AFMS_XY = Adafruit_MotorShield(0x61);

    // Connect a stepper motor with 200 steps per revolution (1.8 degree)

    // to motor port #2 (M3 and M4)

    Adafruit_StepperMotor *stepperZ = AFMS_ZT.getStepper(200, 2);

    // And connect a DC motor to port M1

    Adafruit_DCMotor *myTool = AFMS_ZT.getMotor(1);

    // Connect two stepper motor with 200 steps per revolution (1.8 degree)

    // to motor ports on bottom shield

    Adafruit_StepperMotor *stepperX = AFMS_XY.getStepper(200, 1);

    Adafruit_StepperMotor *stepperY = AFMS_XY.getStepper(200, 2);

    String inputString = ""; // a string to hold incoming data

    boolean stringComplete = false; // whether the string is complete

    long previousMillis = 0; //used for timeout counter

    long timeout = 10000; //timeout length

    // Set up the basic machine position variables

    signed long int Xpos = 0;

    signed long int Ypos = 0;

    signed long int Zpos = 0;

    // Set up the destination machine position variables

    signed long int newXpos = 0;

    signed long int newYpos = 0;

    signed long int newZpos = 0;

    Siliconfish: Arduino XYZ CNC / 3D Printer Do-over http://blog.workingsi.com/2013/02/arduino-xyz-cnc-3d-printer-pc-softwa...

    10 of 20 8/16/2014 10:17 PM

  • void setup()

    {

    // start serial port at 9600 bps:

    Serial.begin(9600);

    inputString.reserve(200);

    establishContact(); // send a serial byte to establish contact until receiver responds

    //Start the PWM

    AFMS_XY.begin(); // create with the default frequency 1.6KHz

    AFMS_ZT.begin(); // create with the default frequency 1.6KHz

    //initialize motors

    initMotors();

    // Home position

    resetPositionCounter();

    Serial.println("Stepper Controller Online;");

    reportCoords();

    }

    void loop()

    {

    // if we get a valid byte, read analog ins:

    if (Serial.available() > 0) {

    // get the new byte:

    char inChar = (char)Serial.read();

    // if the incoming character is a newline, set a flag

    // so the main loop can do something about it:

    if (inChar == ';') {

    stringComplete = true;

    } else {

    // add it to the inputString:

    inputString += inChar;

    }

    // emergency stop command, process immediatly no matter what I'm doing

    if (inChar == '*') emergencyStop();

    if (stringComplete) {

    //Indicate busy

    Serial.print("B;");

    previousMillis = millis(); //set the timeout counter to start

    //Echo the command

    //Serial.print(inputString);

    //decode and do what the command said

    switch( inputString[0] ) {

    case '*' : emergencyStop(); break;

    case 'I' : initMotors(); break;

    case 'T' : setToolSpeed(); break;

    case 'C' : reportCoords(); break;

    case 'P' : relativeZMove(); break;

    case 'Z' : absoluteZMove(); break;

    case 'M' : relativeXYMove(); break;

    case 'A' : absoluteXYMove(); break;

    case 'R' : resetPositionCounter(); break;

    default : break;

    Siliconfish: Arduino XYZ CNC / 3D Printer Do-over http://blog.workingsi.com/2013/02/arduino-xyz-cnc-3d-printer-pc-softwa...

    11 of 20 8/16/2014 10:17 PM

  • }

    //clear the command

    inputString = "";

    stringComplete = false;

    // Indicate ready

    Serial.print("R;");

    }

    }

    }

    // else if ((previousMillis+timeout) > millis()) {

    // //Waited too long for the end of the command

    // intputString = "";

    // stringComplete = false;

    // Serial.println("E;");

    // }

    void establishContact() { //for initial identification

    while (Serial.available() run(RELEASE);

    stepperX->release();

    stepperY->release();

    stepperZ->release();

    //Serial.println("All motors released;");

    }

    void setToolSpeed() {

    signed long int newSpeed = extractCoord(inputString, 0);

    if (newSpeed>0) myTool->run(FORWARD);

    else myTool->run(BACKWARD);

    if (newSpeed == 0) myTool->run(RELEASE);

    else myTool->setSpeed(abs(newSpeed));

    }

    signed long int extractCoord(String numberString, int pos) { //pulls the signed coord from the serial input string

    // pos indicates first or second coord desired

    int splitPos = 0; //location of the : character

    signed long int coord = 0; //temp storage for coords

    signed int sign = 1; //temp storage for coord sign

    char c;

    //First find the position of the :

    for (int i=1; i

  • if( c == '-' ) sign = -1; // capture the sign

    if( c >= '0' && c setSpeed(RPM);

    stepperY->setSpeed(RPM);

    stepperZ->setSpeed(RPM);

    //step motors one step and back to power the coils and hold

    stepperX->step(1, FORWARD, SINGLE);

    stepperY->step(1, FORWARD, SINGLE);

    stepperZ->step(1, FORWARD, SINGLE);

    stepperX->step(1, BACKWARD, SINGLE);

    stepperY->step(1, BACKWARD, SINGLE);

    stepperZ->step(1, BACKWARD, SINGLE);

    }

    void relativeZMove(){

    zMove(Zpos + extractCoord(inputString, 0));

    }

    void absoluteZMove(){

    Siliconfish: Arduino XYZ CNC / 3D Printer Do-over http://blog.workingsi.com/2013/02/arduino-xyz-cnc-3d-printer-pc-softwa...

    13 of 20 8/16/2014 10:17 PM

  • zMove(extractCoord(inputString, 0));

    }

    void relativeXYMove(){

    linearInterpolationMove(Xpos+extractCoord(inputString, 0), Ypos+extractCoord(inputString, 1));

    }

    void absoluteXYMove(){

    linearInterpolationMove(extractCoord(inputString, 0), extractCoord(inputString, 1));

    }

    void linearInterpolationMove ( signed long int newX, signed long int newY) {

    float distance = 0;

    int stepnum = 0;

    signed long int nextX;

    signed long int nextY ;

    signed long int oldX = Xpos;

    signed long int oldY = Ypos;

    //find the hypotenuse, the total distance to be traveled

    distance = sqrt((newX - oldX)*(newX - oldX) + (newY - oldY)*(newY - oldY) ) + 0.5;

    //round to integer number of steps that distance. Step by two to minimize 0 size steps.

    for (stepnum=0; stepnum

  • if ((distance < 8000) && (distance > -8000)) {

    if (distance >= 1) stepperZ->step(distance, FORWARD, SINGLE);

    if (distance step(-1*distance, BACKWARD, SINGLE);

    } else {

    //movement requested is large and likely an error

    Serial.println("ERROR - Z axis range");

    }

    Zpos = newZ; //update machine current position

    }

    Fired up the Java GUI and started clicking buttons. It works! All the buttons are doing theright things. Immediately noticed I needed to make some GUI changes though.

    -Stop button works fine, but once I've done a release I need to have a function for repowering the motors to recover. Using the I; command for that;-Tool speed scale is way too low, need to bump it up --Tool control, I didn't put on a direction button for forward/reverse - Done-I need to look for and obey the busy flags from the arduino - Done, and made a indicatorlight

    Things are working with the Java GUI, the busy light comes on, all the motors move the way Iwant. I'm in business. Here is what it looks like now. It has gotten a bit busy.

    Next step is to figure out what to do on the calibration page.The way this should work is this:

    Start with a calibrated, precisely measured square printed on paper.

    Manually move the XY to a the lower left position

    Hit a button to say it is there

    Manually move the XY to the upper right position

    Enter the size of the square and hit a button to say it is there

    Lower the tool down to touch the work

    Hit a button to say it is at 0

    Lift it and put it down on an object of known thickness

    Enter the height and hit a button to say it is there

    Now the encoders and counters can calculate the size of their steps ininches/mm.

    The units should be changed from counts to inches in the display

    Here is the calibration GUI. Added code to calculate the calibration and reset counters in theArduinos as needed.

    Siliconfish: Arduino XYZ CNC / 3D Printer Do-over http://blog.workingsi.com/2013/02/arduino-xyz-cnc-3d-printer-pc-softwa...

    15 of 20 8/16/2014 10:17 PM

  • Next step is to go back and modify the GUI I previously made for Manual stepping to reportvalues in the calibrated units that calibration measured or in raw steps as it does now. Easyadded the multiply to the calculated position display.

    Alright... now off to figure out how to read and write graphics files. Basic communication andcontrol all seem to be working well with the mockup machine.

    I posted the code for all the parts athttps://code.google.com/p/arduino-java-xyzcnc/downloads/listThis is a working version for manual movement of the machines, haven't implemented the filereading and transferring part yet.

    'm rewriting my Java PC program. The task remaining is to add the file reading andtranslation code to my communication and control software. I need to be able to pick upsome common format CNC files and execute them.

    I want to leverage as much as I can of existing software, and just write a simple line by linetranslator to take an existing file format and convert it to the commands i need to send to theArduino.

    I used HPGL last time, but it is a dead language and is no longer supported by many toolsand graphics editors. It will be really hard to convert pictures into HPGL. I need somethingnew.

    Researching 3D and CNC file formats... Again

    Lots of random scribbling as I google....

    http://answers.yahoo.com/question/index?qid=20110530081859AASSPLv.stl STL is a file format native to the stereolithography CAD software created by 3DSystems..iges The Initial Graphics Exchange Specification (IGES) (pronounced eye-jess) defines aneutral data format that allows the digital exchange of information among Computer-aideddesign (CAD) systems..obj OBJ (or .OBJ) is a geometry definition file format first developed by WavefrontTechnologies for its Advanced Visualizer animation package. The file format is open and hasbeen adopted by other 3D graphics application vendors. For the most part it is a universallyaccepted format..3ds 3DS is one of the file formats used by the Autodesk 3ds Max 3D modeling, animationand rendering software.Gerber - PC board drawing format

    Wood carvers like STL files it seemsDXF shows up too - that is autocad

    This site has a lot of STL fileshttp://www.cnc4free.org/

    Siliconfish: Arduino XYZ CNC / 3D Printer Do-over http://blog.workingsi.com/2013/02/arduino-xyz-cnc-3d-printer-pc-softwa...

    16 of 20 8/16/2014 10:17 PM

  • Tried to read one of the STL files. It is not in ASCII and GIMP can't open it. So that may notbe the best option for me, to write an STL file interpreter. Most people are trying to createthese files, not read them.

    b2G that will convert monochrome .bmp file to stl file

    .bmp I have in the past written many programs that read and write .bmp files. The format ispretty simple XY pixels and intensity. I could use bmp as and easy option, but somethingmore vectory seems better.

    This guy is way ahead of me. I'd have to switch to Linux to borrow his work.http://www.securetech-ns.ca/camm-linux.html

    G-code is used to run cnc machines at the lowest level.

    Some tools for creating gcode http://replicat.org/generators

    This software converts Eagle PCB into gcodehttp://pcbgcode.org/index.php

    cad.py looks like a convertor to gcode

    I looked at gcode on wikipedia and it's fairly hairy. Lots of commands to deal with.

    Windows .bmp picture drawing

    Starting to think I will write a simple bmp drawer to start with.I want to get the tool running with something.

    bmp files say their size and have rows and columns of pixels. Easy to read. I can use gimpto create files of any size, scale them, etc to make them suitable. I'll start with black andwhite bmp files.

    I need to do some googling to make sure there isn't some tool out there I can borrow.

    If I choose to write it myself, the programming is going to go like this:

    Read in the bmp file into an array1.Find the outer extent on top, left and right2.move to the rough center3.put the pen down on a black dot.4.look for a neighbor that is black and move there5.continue until no neighbors are black6.lift7.find another pixel that is black8.move there9.repeat until the drawing is done10.

    I have some old skill code that read bmp files, I will pull that out and use it to start.

    Exploring other options

    Found out vectorizing is called "autotracing". That gave me another thing to google

    There is an "autotracing" program on line.http://vectormagic.com/homeBut the problem is I would then need to be able to read EPS, SVG or PDF files. Maybe thedemo will be enough, but it looks like it costs money.

    Found another that looks free and online. Takes a graphics file and creates vector files.http://www.autotracer.org/

    Siliconfish: Arduino XYZ CNC / 3D Printer Do-over http://blog.workingsi.com/2013/02/arduino-xyz-cnc-3d-printer-pc-softwa...

    17 of 20 8/16/2014 10:17 PM

  • Posted by siliconfish at 9:34 PM

    Labels: Arduino, XYZ CNC

    Tried it, and EPS output looks like a usable, ASCII vector file.

    DXF file is ASCII readable as well. I'm sure this could get hairy, Autocad is prettycomplex. But this file looks manageable.

    SVG looks good too. Seems to be a human readable graphics file that I couldinterpret

    http://en.wikipedia.org/wiki/Scalable_Vector_GraphicsSVG could get out of hand, with lots of shapes and fonts to support. However the basic filelooks good

    This means Move to 30:3, Line to 30:10, Bezier Curve to a list ofcoords, z=end.

    Here is the spec on the SVG file formathttp://www.w3.org/TR/2011/REC-SVG11-20110816/paths.html#PathDataMovetoCommands

    Played with http://www.autotracer.org/ and I'm pretty happy with the files it produces. It isreally for 2D drawing but it makes simple vector files that are easy to turn into tool controlfiles. Gimp can read and display them. Looks like a good quickie option to get off theground.

    This is a little graphic with some letters and a square:

    I will need to implement the Curve function in the Arduino, and convert the control letters tomatch just to make life easier.

    Also found this code for running in a browser:https://code.google.com/p/svg-edit/

    It has a demo which is a fully functional svg editor that produces similar graphics files thatcan be edited. Looks like a winner.http://svg-edit.googlecode.com/svn/branches/2.6/editor/svg-editor.html

    At this point it seems appropriate to start other posts with this topic, this post is getting toolong and covers too much.

    2 comments:

    Siliconfish: Arduino XYZ CNC / 3D Printer Do-over http://blog.workingsi.com/2013/02/arduino-xyz-cnc-3d-printer-pc-softwa...

    18 of 20 8/16/2014 10:17 PM

  • Subscribe to: Post Comments (Atom)

    Comment as:

    Publish

    Create a Link

    thebob May 9, 2013 at 12:40 PM

    I'm watching this blog with baited breath.

    If your encoder could be used first with a probe to map the flatness of a pcb, andthen adjust the Z axis Gcode accordingly, you might have designed the best PCBmill yet!

    Reply

    Elvio Spiteri September 5, 2013 at 3:14 AM

    This is really interesting and I`m tempted to try it out. In fact ... YES I`m going to try itout ! Thanks for the information. GOOD JOB !

    Reply

    Links to this post

    Siliconfish: Arduino XYZ CNC / 3D Printer Do-over http://blog.workingsi.com/2013/02/arduino-xyz-cnc-3d-printer-pc-softwa...

    19 of 20 8/16/2014 10:17 PM

  • Siliconfish: Arduino XYZ CNC / 3D Printer Do-over http://blog.workingsi.com/2013/02/arduino-xyz-cnc-3d-printer-pc-softwa...

    20 of 20 8/16/2014 10:17 PM