Introduction: Control a RepStrap With Processing

About: Married to Domestic_Engineer (but I call her Meghan).

This instructable shows how you can use many openly available projects together to build an interesting and complex system. It draws on several community projects including: RepRap, Arduino, Processing, Linux and, of course, Instructables!

More specifically this intructable shows how to draw the path of a bouncing ball with a CNC machine. But this is primarly an example of this open source toolchain.

The first few steps of this intstructable describe the basic setup I am using and includes links to additional information. This is followed by more specific intructions and code to creaste the drawings.

Here is a breif outline of the setup I am using.
Setup:
Hardware:
1 - RepStrap McWire Carestion Bot
2 - Stepper drivers with firmware from RepRap
3 - PC power supply
4 - Arduino Duemilanove

Software:
1 - Arduino IDE on a computer
2 - Processing software on a computer

Here are some good books on Arduino and Processing:

Programming Arduino Getting Started with Sketches

Processing: A Programming Handbook for Visual Designers and Artists

**NOTE** 7/2013 -- 3D printing is now pretty popular -- there is now an amazon 3D printing store here Amazon 3D printing store

Step 1: The Setup

Here is the setup in detail. All the pieces were built following directions from community projects. In this step I've included descriptions and links for all the hardware and software components for this project. If you follow all the instructions on all these links you will have a setup identical to mine. You can use whatever X-Y CNC platform you can get your hands on. I've listed some alternatives in one of the final steps.

From left to right.

RepStrap
This is "McWire Cartesian Bot v1.2" - It is a version of Tom McGuire's CNC machine which has been adapted by The RepRap group for 3D printing. For simplicity, this Instructable is only using the X-Y axis. You should be able to use any X-Y stage that is driven with stepper motors.

If you would like to build this exact machine, detailed instructions can be found here (http://reprap.org/bin/view/Main/McWire_Cartesian_Bot_1_2) I believe these were posted by Zach Smith of the RepRap team.

Tom McGurie's original instructable is here (https://www.instructables.com/id/Easy-to-Build-Desk-Top-3-Axis-CNC-Milling-Machine/)

"Stepper Drivers"
These driver boards are also the work of the RepRap team. They are "Stepper Motor Driver V1.2" Designed by Zach Hoeken. Full instructions can be found at http://reprap.org/bin/view/Main/Stepper_Motor_Driver_1_2. These include ports for optical endstops. This is a very nice feature, but I am not using it here.

They have new version - Stepper Motor Driver v2.3 which is availble here (http://store.makerbot.com/featured-products/stepper-motor-driver-v2-3-kit.html).

SparkFun is stocking a good looking driver as well (http://www.sparkfun.com/commerce/product_info.php?products_id=9402).

"Power"
The power to the drivers is from a desktop computer power supply. RepRap will also tell you how to do this!

http://dev.www.reprap.org/bin/view/Main/PCPowerSupply

"Arduino with breakout"
This setup is using an Arduino Duemilanove with an Atmega 168 chip. Everything should work with other Arduino's and clones.

This breakout is also from RepRap. It is "Arduino Breakout v1.4" also Designed by Zach Hoeken. And available here. http://store.makerbot.com/electronics/pcbs/arduino-breakout-v1-4-pcb.html

Spark fun is stocking a nice screw sheild as well (http://www.sparkfun.com/commerce/product_info.php?products_id=9282)

"USB cable to PC"
The Arduino is connected to a desktop computer with a USB cable.

"Software on the PC"

I'm running an Ubunto distribution of Linux on my PC, the operating system shouldn't really matter since this project using Arduino and Processing software which is designed to run on most platforms (Linux, Mac, Windows).
If you don't already have them, You will need to load the Arduino and Processing software packages.

http://www.arduino.cc/
http://processing.org/

Step 2: Build a Pen Holder

Ideally you would have a milling tool or plastic extruder mounted on the Z-axis of your desktop CNC machine. Since I have not built those parts for my RepSrap yet, I am using a Sharpie marker clamped to the Z-axis frame.

To build a quick Sharpie holder. Drill a 1/2" hole in through one end of a strip of wood or plastic (approx 1/4?X1.5"X6"). Wrap a bit of duct tape around the Sharpie for traction. Then stick the sharpie through the hold and clip it inplace with two binder clips, as shown below. This holds reasonalby will and can be quickly adjusted. Once you are ready to start "printint" you just clamp the strip of wood to the fram of the Z-axis, or whatever is handy.

Step 3: Arduino Wiring:

Arduino Wiring:

It is important to have stepper motor drivers wired to the stepper motor correctly. In this case, 'correclty' means that the Arduino to Stepper driver connections match the pins called out in the Arduino and Processing Code that follows.

Wire the stepper motor to the Arduino like this:

X - Driver "Arduino" "What it does"
Pin 3 2 Step
Pin 4 3 Direction

Y - Driver "Arduino" "What it does"
Pin 3 10 Step
Pin 4 7 Direction

This is the same setup used by RepRap.org (http://make.rrf.org/electronics-2.0). So if you have a half built RapRap you are all set!

Step 4: Arduino Code

"Arduino Code:"

This project requires to peices of code. 'Firmware' that is loaded onto the Arduino microcontroller. And 'Software' that is run by the Processing program on the PC.

The chain of command goes like this - Processing -> Ardcuino Board -> Steppr drivers -> stepper motors -> X-Y stages.

Here is a little more detail of the communication that will be happening, based on my understanding of the way things work....

The Processing software will send commands to the Arduino board over the USB cable. T The Arduino board will take the command and set the specifed output pins to high or low logic states (5V or 0V). The stepper drivers are wired to the Arduino board outputs. So when the drivers see the high and low signals, they send power to the approriate coils in the stepper motors, making them go.

The code below sets up the Arduino board to listen for the commands sent from Processing and then take actions.

You can cut and paste the code in the Arduino IDE. Then verify the code by clicking the 'Play" button. If there are no errors you can then upload it to the board by pressing the upload button - which looks like a right arrow.



// Arduino code:

// Read data from the serial and turn ON or OFF a light depending on the value
//and control stepper motor on RepStrap
char val; // Data received from the serial port
int ledPin = 13; // Set the pin to digital I/O 13

#define XstepPin 10
#define XdirPin 7

#define YstepPin 2
#define YdirPin 3

void setup() {

pinMode(ledPin, OUTPUT); // Set pin as OUTPUT
pinMode(XstepPin, OUTPUT);
pinMode(XdirPin, OUTPUT);
pinMode(YstepPin, OUTPUT);
pinMode(YdirPin, OUTPUT);
Serial.begin(9600); // Start serial communication at 9600 bps
}

void loop() {
if (Serial.available()) { // If data is available to read,
val = Serial.read(); // read it and store it in val
}
if (val == 'H') { // If H was received
digitalWrite(ledPin, HIGH); // turn the LED on
digitalWrite(XdirPin,HIGH);
digitalWrite(XstepPin,HIGH);

delayMicroseconds(2);
digitalWrite(XstepPin,LOW);
delayMicroseconds(2);
}

if(val == 'h') {
digitalWrite(ledPin, HIGH); // turn the LED on
digitalWrite(YdirPin,HIGH);
digitalWrite(YstepPin,HIGH);

delayMicroseconds(2);
digitalWrite(YstepPin,LOW);
delayMicroseconds(2);

}
if (val == 'L'){
digitalWrite(ledPin, LOW); // Otherwise turn it OFF
digitalWrite(XdirPin,LOW);
digitalWrite(XstepPin,HIGH);

delayMicroseconds(2);
digitalWrite(XstepPin,LOW);
delayMicroseconds(2);
}

if (val == 'l'){
digitalWrite(ledPin, LOW); // Otherwise turn it OFF
digitalWrite(YdirPin,LOW);
digitalWrite(YstepPin,HIGH);

delayMicroseconds(2);
digitalWrite(YstepPin,LOW);
delayMicroseconds(2);
}

delayMicroseconds(1000); // <<<<<< USE TO CHANGE SPEED <<<<<<<<
}

Step 5: Processing Code

"Processing Code"

Here is the Processing code. Open Processing and cut and paste the code.

This code is built on an example from the Processing text book written by Casey Reas and Ben Fry. (http://www.amazon.com/Processing-Programming-Handbook-Designers-Artists/dp/0262182629)


//This outputs the motion of the bouncing ball to the RepRap X and Y axis

import processing.serial.*;

Serial myPort; // Create object from Serial class
int val; // Data received from the serial port

float x= 50.0;
float y = 50.0;
float speedX = 1.0;
float speedY= .4;
float radius = 15.0;
int timeDelay = 10; //10 ms delay between direction prints gives rocky step
int directionX = 1;
int directionY = 1;

void setup(){
size(100, 100);
smooth();
noStroke();
ellipseMode(RADIUS);

String portName = Serial.list()[0];
myPort = new Serial(this, portName, 9600);
}

void draw(){
fill(0,12);
rect(0,0,width, height);
fill(255);
ellipse(x, y, radius, radius);

x += speedX * directionX;

if (directionX == 1){ //if the direction is up, the motor goes one way
myPort.write('H');
print('H');
delay(100);
}
else { // if the direction is down, the motor goes the other way
myPort.write('L'); // send an L otherwise
print('L');
delay(100);
}

if((x>width-radius) || (x < radius)) {
directionX = -directionX;
}

y += speedY * directionY;

if (directionY == 1){ //if the direction is up, the motor goes one way
myPort.write('h');
print('h');
delay(100);
}
else { // if the direction is down, the motor goes the other way
myPort.write('l'); // send an L otherwise
print('l');
delay(100);
}

if((y>height-radius) || (y < radius)) {
directionY = -directionY;
}

}

Step 6: Run the Processing Code

"Run the Processing Code:"

Confirm that power is OFF to the stepper motors.

Run the Processing code by clicking the 'Play' button.

You should see:
1 - A display window on the computer monitor showing the ball slowly bouncing around.
2 - The LEDs on the Arduino and stepper boards blinking.

The H,h,L,l outputs are printed on the bottom of the screen, they are also sent over the USB cable to the Aduino board.

Step 7: Draw!

Draw!

Now that the path of the bouncing ball is being sent to the Arduino Board, it is time to set up the paper and pen.

- Tape a peice of paper to the X-Y platform.
- Clip a pen to the Z-axis frame.

-Check that the ball is still bouning and the lights are still blining.

-Turn on power to the stepper motors!

-Now the X-Y platform will move about following the path of the bouncing ball. Yay!


Step 8: Make Changes

"Make changes:"

Now you can mess around with the code to change the behavior of the ball, which will change the comands to the robot and it will draw somehting different.

Changing the size of the box will make a bigger drawing.

You can also:
Change speed
Change the X or Y bounce


You will probably notice that the steppers are not running very smoothly. I'll post some new code once this is fixed.

Alternatives and ideas:
-You can do almost this exact instructable using the Arduino "Frimata" library. I don't know if there is much advantage either way.
-Ultimately would like to print 3D objects that are generated from Processing. I'd like to print 3D fractals, but I am a long way off for now!

Step 9: Making It a Little Better


As I make improvements I am going to add steps to the end of this instructable. 

10-11-09

The previus code tracks the ball pretty well but the steppers are driven in a very rocky way.

In this updated code, the Proccessing sketch only sends a signal to the Arduino when there is a change in direction.  So the stepper motors just run in whatever direction they were last set to, until they are told to change.    This allows the motors to run alot faster and smoother. 

But there is still somthing a bit off.  The Arduino seems to miss some of the signals, so the RepStrap ends up with the X-Y stage pushed all the way to one side. 

I will try to fix this. 

The Arduino and Processing code is below.  I have added more comments to help keep things clear.


/////////////////////////////////////////////////
// Arduino code:

// Read data from the serial
//Use data to determine direction of X and Y steppers


#define XstepPin 10
#define XdirPin 7

#define YstepPin 2
#define YdirPin 3

int val; // Data received from the serial port

void setup() {

pinMode(XstepPin, OUTPUT);
pinMode(XdirPin, OUTPUT);
pinMode(YstepPin, OUTPUT);
pinMode(YdirPin, OUTPUT);
Serial.begin(9600); // Start serial communication at 9600 bps
}

void loop() {
  int dirX;
  int dirY;
if (Serial.available()) { // If data is available to read,
   val = Serial.read(); // then read it and store value in val
}

if (val == 'H'){        //set the direction of X and Y based on data sent from Processing
    dirX = HIGH;
}
if (val == 'L'){
  dirX = LOW;
}

if (val == 'h'){
    dirY = HIGH;
    }
if (val == 'l'){
    dirY = LOW;
    }

digitalWrite(XdirPin,dirX);    //set X direction
digitalWrite(YdirPin,dirY);    //set Y direction
digitalWrite(XstepPin,HIGH);      //take steps
digitalWrite(YstepPin,HIGH);     
delayMicroseconds(2);
digitalWrite(XstepPin,LOW);
digitalWrite(YstepPin,LOW);
delayMicroseconds(2);


delayMicroseconds(1000); // <<<<<< USE TO CHANGE SPEED <<<<<<<<
}

///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
//Processing Code:
//This outputs the motion of the bouncing ball to the RepRap X and Y axis

import processing.serial.*;

Serial myPort; // Create object from Serial class
int val;

float x= 50.0;
float y = 50.0;
float speedX = 1.0;
float speedY= .4;
float radius = 15.0;
int directionX = 1;
int directionY = 1;
int old_directionX = 1;
int old_directionY = 1;

void setup(){
size(100, 100);
smooth();
noStroke();
ellipseMode(RADIUS);

String portName = Serial.list()[0];
myPort = new Serial(this, portName, 9600);
}

void draw(){
fill(0,12);
rect(0,0,width, height);
fill(255);
ellipse(x, y, radius, radius);

x += speedX * directionX;
if((x>width-radius) || (x < radius)) {  //change X direction if the ball hits the side of the box
directionX = -directionX;
}

y += speedY * directionY;
if((y>height-radius) || (y < radius)) {  //change Y direction if the ball hits the side of the box
directionY = -directionY;
}



if ((directionX != old_directionX) && (directionX == 1)){ //if X direction changed print H
myPort.write('H');
print('H');
delay(100);
}

if ((directionX != old_directionX) && (directionX == -1)){ //if X direction changed print h
myPort.write('h');
print('h');
delay(100);
}

if ((directionY != old_directionY) && (directionY == 1)){ //if Y direction changed print L
myPort.write('L');
print('L');
delay(100);
}

if ((directionY != old_directionY) && (directionY == -1)){ //if Y direction changed print l
myPort.write('l');
print('l');
delay(100);
}

old_directionX = directionX ;  //stores the directions we just used, as the old direction
old_directionY= directionY;

//delay(100); //uncomment to slow the whole thing down for troubleshooting
}






Step 10: Doing It With Firmata

Here is an alternative approach that uses the Firmata library to change the direction of the stepper motor from Processing.

You can learn more about it here:
http://arduino.cc/en/Reference/Firmata
and here:
http://firmata.org/wiki/Main_Page

I don't understand the details.  But, from my experience so far, I do know that is  does a good job of handling the communication between the PC and the Arduino.  So, I am happy to ignore the details for now.

I have started by modifying an example that is included in theArduinoIDE called "SimpleDigitalFirmata".  Once this code is loaded onto the Arduino,  You can communicate with the digital pins on the Arduino board directly from Processing.

In processing I am working from an example that turns on and off an LED on the Arduino board when you move a mouse over a square dawn of the monitor of the PC.

To make Processing control the LED and a Stepper motor, you need to modiify the code for the Arduino and Processing.  

On the Arduino side - I've defined the stepper pins at the top of the sketch.  Then I jammed in code to drive the stepper at the end of the main loop.  I put this outside of the code that reads the serial port.  So the stepper will just go.  

The direction of the stepper is set directly from Processing.  The example code turned on and off an LED on pin13.  So, I just made the step direction pin do the same thing as the LED.

Here is the code.  This only controls the X stepper.

///////////////// ARDUINO //////////////////////
//Supports as many digital inputs and outputs as possible.
//
//This example code is in the public domain.

#include

#define XstepPin 10            //Step pin
#define XdirPin 7                 //Direction pin

byte previousPIN[2];  // PIN means PORT for input
byte previousPORT[2];

void outputPort(byte portNumber, byte portValue)
{
// only send the data when it changes, otherwise you get too many messages!
    if(previousPIN[portNumber] != portValue) {
        Firmata.sendDigitalPort(portNumber, portValue);
        previousPIN[portNumber] = portValue;
        Firmata.sendDigitalPort(portNumber, portValue);
    }
}

void setPinModeCallback(byte pin, int mode) {
    if(pin > 1) { // don't touch RxTx pins (0,1)
        pinMode(pin, mode);
    }
}

void digitalWriteCallback(byte port, int value)
{
    byte i;
    byte currentPinValue, previousPinValue;

    if(value != previousPORT[port]) {
        for(i=0; i<8; i++) {
            currentPinValue = (byte) value & (1 << i);
            previousPinValue = previousPORT[port] & (1 << i);
            if(currentPinValue != previousPinValue) {
                digitalWrite(i + (port*8), currentPinValue);
            }
        }
        previousPORT[port] = value;
    }
}

void setup()
{
    Firmata.setFirmwareVersion(0, 1);
    Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
    Firmata.attach(SET_PIN_MODE, setPinModeCallback);
    Firmata.begin(57600);
}

void loop()
{
    outputPort(0, PIND &~ B00000011); // pins 0-7, ignoring Rx/Tx pins (0/1)
    outputPort(1, PINB); // pins 8-13
    while(Firmata.available()) {
        Firmata.processInput();
    }

//added stepper sequence to firmata code
digitalWrite(XstepPin,HIGH);    //take steps   
delayMicroseconds(2);

digitalWrite(XstepPin,LOW);
delayMicroseconds(2);
delayMicroseconds(1000); //  <<<<<< USE TO CHANGE STEPPER SPEED <<<<<<<<


}


//////////////////////////////////Processing/////////////////////////////////
/**
 * Simple Write. < modified to control stepper direction
 *
 * Check if the mouse is over a rectangle and writes the status to the serial port.
 * This example works with the Wiring / Arduino program that follows below.
 */


import processing.serial.*;
import cc.arduino.*;

Arduino arduino;

//Serial myPort;  // Create object from Serial class
      // Data received from the serial port
int ledPin = 13;              // pin for LED
int XdirPin = 7;             // pin for stepper X direction
int XstepPin = 10;        //pin for X step


void setup()
{
  size(200, 200);
  // I know that the first port in the serial list on my mac
  // is always my  FTDI adaptor, so I open Serial.list()[0].
  // On Windows machines, this generally opens COM1.
  // Open whatever port is the one you're using.
 // String portName = Serial.list()[0];
  //myPort = new Serial(this, portName, 9600);
  arduino = new Arduino(this, Arduino.list()[0], 57600); // v1
  arduino.pinMode(ledPin, Arduino.OUTPUT);
  arduino.pinMode(XdirPin, Arduino.OUTPUT);

}

void draw() {
  background(255);
  if (mouseOverRect() == true) {  // If mouse is over square,
    fill(204);                    // change color and
    arduino.digitalWrite(ledPin, Arduino.HIGH);              // LED on
    arduino.digitalWrite(XdirPin, Arduino.HIGH);            // Stepper direction this way


  }
  else {                        // If mouse is not over square,
    fill(0);                      // change color and
    arduino.digitalWrite(ledPin, Arduino.LOW);      // LED off
    arduino.digitalWrite(XdirPin, Arduino.LOW);    //Stepper direction the other way


  }
  rect(50, 50, 100, 100);         // Draw a square
}

boolean mouseOverRect() { // Test if mouse is over square
  return ((mouseX >= 50) && (mouseX <= 150) && (mouseY >= 50) && (mouseY <= 150));
}



Step 11: Correction to Firmata....

It looks like something is wrong in step 10, which is making it so the stepper motor doesn't run.

The code below works - but doesn't have as many comments.

//////////////////////////Arduino//////////////////////////

// Wiring/Arduino code:// simmple digital firmata
  //Supports as many digital inputs and outputs as possible.

  //This example code is in the public domain.

#include <Firmata.h>

#define XstepPin 10
#define XdirPin 7

#define YstepPin 2
#define YdirPin 3

byte previousPIN[2];  // PIN means PORT for input
byte previousPORT[2];

void outputPort(byte portNumber, byte portValue)
{
// only send the data when it changes, otherwise you get too many messages!
    if(previousPIN[portNumber] != portValue) {
        Firmata.sendDigitalPort(portNumber, portValue);
        previousPIN[portNumber] = portValue;
        Firmata.sendDigitalPort(portNumber, portValue);
    }
}

void setPinModeCallback(byte pin, int mode) {
    if(pin > 1) { // don't touch RxTx pins (0,1)
        pinMode(pin, mode);
    }
}

void digitalWriteCallback(byte port, int value)
{
    byte i;
    byte currentPinValue, previousPinValue;

    if(value != previousPORT[port]) {
        for(i=0; i<8; i++) {
            currentPinValue = (byte) value & (1 << i);
            previousPinValue = previousPORT[port] & (1 << i);
            if(currentPinValue != previousPinValue) {
                digitalWrite(i + (port*8), currentPinValue);
            }
        }
        previousPORT[port] = value;
    }
}

void setup()
{
    Firmata.setFirmwareVersion(0, 1);
    Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
    Firmata.attach(SET_PIN_MODE, setPinModeCallback);
    Firmata.begin(57600);
}

void loop()
{
    outputPort(0, PIND &~ B00000011); // pins 0-7, ignoring Rx/Tx pins (0/1)
    outputPort(1, PINB); // pins 8-13
    while(Firmata.available()) {
        Firmata.processInput();
    }

//added stepper sequence to firmata code
digitalWrite(XstepPin,HIGH);    //take steps
digitalWrite(YstepPin,HIGH);     
delayMicroseconds(2);
digitalWrite(XstepPin,LOW);
digitalWrite(YstepPin,LOW);
delayMicroseconds(2);
delayMicroseconds(1000); //  <<<<<< USE TO CHANGE STEPPER SPEED???? <<<<<<<<


}


/////////////////////////////PROCESSING//////////////////////////////////////

/**
 * Simple Write.
 *
 * Check if the mouse is over a rectangle and writes the status to the serial port.
 * This example works with the Wiring / Arduino program that follows below.
 */


import processing.serial.*;
import cc.arduino.*;

Arduino arduino;

//Serial myPort;  // Create object from Serial class
      // Data received from the serial port
int ledPin = 13;
int XstepPin = 10;
int XdirPin = 7;



void setup()
{
  size(200, 200);
  // I know that the first port in the serial list on my mac
  // is always my  FTDI adaptor, so I open Serial.list()[0].
  // On Windows machines, this generally opens COM1.
  // Open whatever port is the one you're using.
 // String portName = Serial.list()[0];
  //myPort = new Serial(this, portName, 9600);
  arduino = new Arduino(this, Arduino.list()[0], 57600); // v1
  arduino.pinMode(ledPin, Arduino.OUTPUT);
  arduino.pinMode(XstepPin, Arduino.OUTPUT);
  arduino.pinMode(XdirPin, Arduino.OUTPUT);

}

void draw() {
  background(255);
  if (mouseOverRect() == true) {  // If mouse is over square,
    fill(204);                    // change color and
    arduino.digitalWrite(ledPin, Arduino.HIGH);              // send an H to indicate mouse is over square
    arduino.digitalWrite(XdirPin, Arduino.HIGH);
    //arduino.digitalWrite(XstepPin, Arduino.HIGH);
    //delay(1);
    //arduino.digitalWrite(XstepPin, Arduino.LOW);
    //delay(1);

  }
  else {                        // If mouse is not over square,
    fill(0);                      // change color and
    arduino.digitalWrite(ledPin, Arduino.LOW);      // send an L otherwise
    arduino.digitalWrite(XdirPin, Arduino.LOW);
    //arduino.digitalWrite(XstepPin, Arduino.HIGH);
    //delay(1);
    //arduino.digitalWrite(XstepPin,Arduino.LOW);
    //delay(1);

  }
  rect(50, 50, 100, 100);         // Draw a square
}

boolean mouseOverRect() { // Test if mouse is over square
  return ((mouseX >= 50) && (mouseX <= 150) && (mouseY >= 50) && (mouseY <= 150));
}




Step 12: Corrected and Commented

Here is a third pass at the Firmata code.

This should work and includes comments. 

///////////////// ARDUINO //////////////////////
/* Supports as many digital inputs and outputs as possible.
 *<modified to drive a stepper motor
 * This example code is in the public domain.
 */
#include <Firmata.h>

#define XstepPin 10            //Step pin
#define XdirPin 7                 //Direction pin

byte previousPIN[2];  // PIN means PORT for input
byte previousPORT[2];

void outputPort(byte portNumber, byte portValue)
{
// only send the data when it changes, otherwise you get too many messages!
    if(previousPIN[portNumber] != portValue) {
        Firmata.sendDigitalPort(portNumber, portValue);
        previousPIN[portNumber] = portValue;
        Firmata.sendDigitalPort(portNumber, portValue);
    }
}

void setPinModeCallback(byte pin, int mode) {
    if(pin > 1) { // don't touch RxTx pins (0,1)
        pinMode(pin, mode);
    }
}

void digitalWriteCallback(byte port, int value)
{
    byte i;
    byte currentPinValue, previousPinValue;

    if(value != previousPORT[port]) {
        for(i=0; i<8; i++) {
            currentPinValue = (byte) value & (1 << i);
            previousPinValue = previousPORT[port] & (1 << i);
            if(currentPinValue != previousPinValue) {
                digitalWrite(i + (port*8), currentPinValue);
            }
        }
        previousPORT[port] = value;
    }
}

void setup()
{
    Firmata.setFirmwareVersion(0, 1);
    Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
    Firmata.attach(SET_PIN_MODE, setPinModeCallback);
    Firmata.begin(57600);
}

void loop()
{
    outputPort(0, PIND &~ B00000011); // pins 0-7, ignoring Rx/Tx pins (0/1)
    outputPort(1, PINB); // pins 8-13
    while(Firmata.available()) {
        Firmata.processInput();
    }

//added stepper sequence to firmata code
//digitalWrite(XdirPin,HIGH);
digitalWrite(XstepPin,HIGH);    //take steps   
delayMicroseconds(2);
digitalWrite(XstepPin,LOW);
delayMicroseconds(2);
delayMicroseconds(1000); //  <<<<<< USE TO CHANGE STEPPER SPEED <<<<<<<<


}




//////////////////////PROCESSING///////////////////////////////////

//
 // Simple Write. < modified to control stepper direction
 //
 //Check if the mouse is over a rectangle and writes the status to the serial port.
 //This example works with the Wiring / Arduino program that follows below.
 //


import processing.serial.*;
import cc.arduino.*;

Arduino arduino;

//Serial myPort;  // Create object from Serial class
      // Data received from the serial port
int ledPin = 13;              // pin for LED
int XdirPin = 7;             // pin for stepper X direction
int XstepPin = 10;



void setup()
{
  size(200, 200);
  // I know that the first port in the serial list on my mac
  // is always my  FTDI adaptor, so I open Serial.list()[0].
  // On Windows machines, this generally opens COM1.
  // Open whatever port is the one you're using.
 // String portName = Serial.list()[0];
  //myPort = new Serial(this, portName, 9600);
  arduino = new Arduino(this, Arduino.list()[0], 57600); // v1
  arduino.pinMode(ledPin, Arduino.OUTPUT);
  arduino.pinMode(XdirPin, Arduino.OUTPUT);

}

void draw() {
  background(255);
  if (mouseOverRect() == true) {  // If mouse is over square,
    fill(204);                    // change color and
    arduino.digitalWrite(ledPin, Arduino.HIGH);              // LED on
    arduino.digitalWrite(XdirPin, Arduino.HIGH);            // Stepper direction this way


  }
  else {                        // If mouse is not over square,
    fill(0);                      // change color and
    arduino.digitalWrite(ledPin, Arduino.LOW);      // LED off
    arduino.digitalWrite(XdirPin, Arduino.LOW);    //Stepper direction the other way


  }
  rect(50, 50, 100, 100);         // Draw a square
}

boolean mouseOverRect() { // Test if mouse is over square
  return ((mouseX >= 50) && (mouseX <= 150) && (mouseY >= 50) && (mouseY <= 150));
}




Step 13: Follow the Bouncing Ball With Firmata! (this Works Good)

http://www.youtube.com/watch?v=VYgbStFaQbM

Now I've taken the bouncing ball sketch and combined it with the Firmata one. 

Now the stepper motors smoothly follow the path of the bouncing ball!! 

Now we are getting somewhere!


//////////////////////////Arduino//////////////////////////

// Wiring/Arduino code:// simmple digital firmata
  //Supports as many digital inputs and outputs as possible.

  //This example code is in the public domain.

#include <Firmata.h>

#define XstepPin 10
#define XdirPin 7

#define YstepPin 2
#define YdirPin 3

byte previousPIN[2];  // PIN means PORT for input
byte previousPORT[2];

void outputPort(byte portNumber, byte portValue)
{
// only send the data when it changes, otherwise you get too many messages!
    if(previousPIN[portNumber] != portValue) {
        Firmata.sendDigitalPort(portNumber, portValue);
        previousPIN[portNumber] = portValue;
        Firmata.sendDigitalPort(portNumber, portValue);
    }
}

void setPinModeCallback(byte pin, int mode) {
    if(pin > 1) { // don't touch RxTx pins (0,1)
        pinMode(pin, mode);
    }
}

void digitalWriteCallback(byte port, int value)
{
    byte i;
    byte currentPinValue, previousPinValue;

    if(value != previousPORT[port]) {
        for(i=0; i<8; i++) {
            currentPinValue = (byte) value & (1 << i);
            previousPinValue = previousPORT[port] & (1 << i);
            if(currentPinValue != previousPinValue) {
                digitalWrite(i + (port*8), currentPinValue);
            }
        }
        previousPORT[port] = value;
    }
}

void setup()
{
    Firmata.setFirmwareVersion(0, 1);
    Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
    Firmata.attach(SET_PIN_MODE, setPinModeCallback);
    Firmata.begin(57600);
}

void loop()
{
    outputPort(0, PIND &~ B00000011); // pins 0-7, ignoring Rx/Tx pins (0/1)
    outputPort(1, PINB); // pins 8-13
    while(Firmata.available()) {
        Firmata.processInput();
    }

//added stepper sequence to firmata code
digitalWrite(XstepPin,HIGH);    //take steps
digitalWrite(YstepPin,HIGH);     
delayMicroseconds(2);
digitalWrite(XstepPin,LOW);
digitalWrite(YstepPin,LOW);
delayMicroseconds(2);
delayMicroseconds(1000); //  <<<<<< USE TO CHANGE STEPPER SPEED???? <<<<<<<<


}


///////////////////PROCESSING//////////////////////////////
/**
 * Simple Write.
 *
 * Check if the mouse is over a rectangle and writes the status to the serial port.
 * This example works with the Wiring / Arduino program that follows below.
 */


import processing.serial.*;
import cc.arduino.*;

Arduino arduino;

//Serial myPort;  // Create object from Serial class
      // Data received from the serial port
int ledPin = 13;
int XstepPin = 10;
int XdirPin = 7;
int YstepPin = 2;
int YdirPin = 3;

//parameters for the ball
float x= 50.0;
float y = 50.0;
float speedX = 1.0;
float speedY= .4;
float radius = 15.0;
int directionX = 1;
int directionY = 1;


void setup()
{
  //setup the drawing
  size(100, 100);
  smooth();
  noStroke();
  ellipseMode(RADIUS);

  //setup communication with Arduino
  arduino = new Arduino(this, Arduino.list()[0], 57600); // v1
  arduino.pinMode(ledPin, Arduino.OUTPUT);
  arduino.pinMode(XstepPin, Arduino.OUTPUT);
  arduino.pinMode(XdirPin, Arduino.OUTPUT);
  arduino.pinMode(YstepPin, Arduino.OUTPUT);
  arduino.pinMode(YdirPin, Arduino.OUTPUT);

}

void draw() {
  fill(0,12);
  rect(0,0,width, height);
  fill(255);
  ellipse(x, y, radius, radius);

  x += speedX * directionX;
  if((x>width-radius) || (x < radius)) {  //change X direction if the ball hits the side of the box
  directionX = -directionX;
    }

  y += speedY * directionY;
  if((y>height-radius) || (y < radius)) {  //change Y direction if the ball hits the side of the box
  directionY = -directionY;
    }

  if (directionX >= 0){
    arduino.digitalWrite(ledPin, Arduino.HIGH);              
    arduino.digitalWrite(XdirPin, Arduino.HIGH);
      }
      else{
        arduino.digitalWrite(ledPin, Arduino.LOW);              
        arduino.digitalWrite(XdirPin, Arduino.LOW);
       }

  if (directionY >= 0){
    //arduino.digitalWrite(ledPin, Arduino.HIGH);              
    arduino.digitalWrite(YdirPin, Arduino.HIGH);
      }
      else{
        //arduino.digitalWrite(ledPin, Arduino.LOW);              
        arduino.digitalWrite(YdirPin, Arduino.LOW);
       }
}


Step 14: Working Towards a 3D Print

The RepRap builds up 3D objects with melted plastic. Each layer is laid down as a plastic mesh.  There is softwar/firmware availalbe to generate this mesh for any 3D object.  But I am interested in making a program that will print the shapes directly from Processing.

I'm starting by modifiying the bouncing ball sketch to draw a mesh that will cover a 2D shape.

The next step will be to rotated the mesh 90deg and repeat (to print the next layer).

Here is what I have so far - this is only in Processing and does not include any communitation with the Arduino.



///////////////////Processing/////////////
/**
 *ball traces back and forth across the window
 */

int size = 10;       // Width of the shape
float xpos, ypos;    // Starting position of shape   

float xspeed = 3;  // Speed of the shape
float yspeed = 0;// Speed of the shape

int xdirection = 1;  // Left or Right
int ydirection = 1;  // Top to Bottom


void setup()
{
  size(200, 200);
  noStroke();
  frameRate(30);
  smooth();
  // Set the starting position of the shape
  xpos = 0;
  ypos = 0;
background(102);
}

void draw()
{
   //background(102);
  // Update the position of the shape
  xpos = xpos + ( xspeed * xdirection );
  ypos = ypos + ( yspeed * ydirection );

  // change direction when the ball hits the edge - to draw a square

    //starts at left and moves towards right

    //move down 10 steps
  if (xpos > width-size && ypos== 0) { //down
    ydirection=1;
    yspeed =2;
    xspeed=0;
  }

     //reverse X direction until it hits the 0X edge
  if(xpos>width-size && ypos ==20){
    xdirection = -1;
    yspeed = 0;
    xspeed =2;
  }

      //move down 10 steps
 if (xpos < 0 && ypos ==20) { //down
    ydirection=1;
    yspeed =2;
    xspeed=0;
  }

  //reverse X direction until it hiths the 200X edge
  if(xpos < 0 && ypos ==40){
    xdirection = 1;
    yspeed = 0;
    xspeed =2;
  }
    //move down 10 steps
      if (xpos > width-size && ypos ==40) { //down
    ydirection=1;
    yspeed =2;
    xspeed=0;
  }

       //reverse X direction until it hits the 0X edge
  if(xpos>width-size && ypos ==60){
    xdirection = -1;
    yspeed = 0;
    xspeed =2;
  }

        //move down 10 steps
 if (xpos < 0 && ypos ==60) { //down
    ydirection=1;
    yspeed =2;
    xspeed=0;
  }

    //reverse X direction until it hits the 200X edge
  if(xpos < 0 && ypos ==80){
    xdirection = 1;
    yspeed = 0;
    xspeed =2;
  }

      //move down 10 steps
      if (xpos > width-size && ypos ==80) { //down
    ydirection=1;
    yspeed =2;
    xspeed=0;
  }

        //reverse X direction until it hits the 0X edge
  if(xpos>width-size && ypos ==100){
    xdirection = -1;
    yspeed = 0;
    xspeed =2;
  }
         //move down 10 steps
 if (xpos < 0 && ypos ==100) { //down
    ydirection=1;
    yspeed =2;
    xspeed=0;
  }
    //reverse X direction until it hiths the 200X edge
        if (xpos < 0 && ypos ==120) { //down
    xdirection=1;
    yspeed =0;
    xspeed=2;
  }

  //move down 10 steps
   if (xpos > width-size && ypos ==120) {
    ydirection=1;
    yspeed =2;
    xspeed=0;
   }
   //reverse direction until it hits teh 0X edge
    if (xpos > width-size && ypos ==140) {
    xdirection=-1;
    yspeed =0;
    xspeed=2;
    }
    //move down 10 steps
         if (xpos < 0 && ypos ==140) { //down
    ydirection=1;
    yspeed =2;
    xspeed=0;
         }
    //reverse X direction until it hiths the 200X edge

   if (xpos < 0 && ypos ==160) { //down
    xdirection=1;
    yspeed =0;
    xspeed=2;
         }
    //move down 10 steps
       if (xpos > width-size && ypos ==160) {
    ydirection=1;
    yspeed =2;
    xspeed=0;
   }
    //reverse direction until it hits teh 200X edge
       if (xpos > width-size && ypos ==180) {
    xdirection=-1;
    yspeed =0;
    xspeed=2;
    }
       //move down 10 steps
       if (xpos > 0 && ypos ==180) {
    ydirection=1;
    yspeed =2;
    xspeed=0;
   }
      //reverse direction until it hits teh 200x edge
       if (xpos > 0 && ypos ==200) {
    xdirection=1;
    yspeed =0;
    xspeed=2;
    }

  // Draw the shape
  ellipse(xpos+size/2, ypos+size/2, size, size);

}

Step 15: Working Towards a 3D Print ....


The code is step 14 needs to be tweaked a bit in order to the stepper motors.  The main change that whenever the balls speed is zero - the corresponding stepper needs to be disabled.

Here is the processing code.  This only runs one layer, many layers need to be stacked to make a 3D print.

///////////////////Processing/////////////
/**
 *ball traces back and forth across the window in a mesh that will be useful for plastic printing
 */

import processing.serial.*;
import cc.arduino.*;

Arduino arduino;

int ledPin = 13;

int XstepPin = 2;
int XdirPin = 3;
int XenablePin = 4;

int YstepPin = 7;
int YdirPin = 10;
int YenablePin = 8;

int size = 10;       // Width of the shape
float xpos, ypos;    // Starting position of shape  

float xspeed = 3;  // Speed of the shape
float yspeed = 0;// Speed of the shape

int directionX = 1;  // Left or Right
int directionY = 1;  // Top to Bottom



void setup()
{
  size(200, 200);
  noStroke();
  frameRate(30);
  smooth();
  // Set the starting position of the shape
  xpos = 0;
  ypos = 0;
background(102);

  //setup communication with Arduino
  arduino = new Arduino(this, Arduino.list()[0], 57600); // v1
  arduino.pinMode(XstepPin, Arduino.OUTPUT);
  arduino.pinMode(XdirPin, Arduino.OUTPUT);
  arduino.pinMode(YstepPin, Arduino.OUTPUT);
  arduino.pinMode(YdirPin, Arduino.OUTPUT);
  arduino.pinMode(EstepPin, Arduino.OUTPUT);
  arduino.pinMode(EdirPin, Arduino.OUTPUT);
  arduino.pinMode(EenablePin, Arduino.OUTPUT);
}

void draw()
{
   //background(102);
  // Update the position of the shape
  xpos = xpos + ( xspeed * directionX );
  ypos = ypos + ( yspeed * directionY );

  // change direction when the ball hits the edge - to draw a square

    //starts at left and moves towards right

    //move down 10 steps
  if (xpos > width-size && ypos== 0) { //down
    directionY=1;
    yspeed =2;
    xspeed=0;
  }

     //reverse X direction until it hits the 0X edge
  if(xpos>width-size && ypos ==20){
    directionX = -1;
    yspeed = 0;
    xspeed =2;
  }

      //move down 10 steps
 if (xpos < 0 && ypos ==20) { //down
    directionY=1;
    yspeed =2;
    xspeed=0;
  }

  //reverse X direction until it hiths the 200X edge
  if(xpos < 0 && ypos ==40){
    directionX = 1;
    yspeed = 0;
    xspeed =2;
  }
    //move down 10 steps
      if (xpos > width-size && ypos ==40) { //down
    directionY=1;
    yspeed =2;
    xspeed=0;
  }

       //reverse X direction until it hits the 0X edge
  if(xpos>width-size && ypos ==60){
    directionX = -1;
    yspeed = 0;
    xspeed =2;
  }

        //move down 10 steps
 if (xpos < 0 && ypos ==60) { //down
    directionY=1;
    yspeed =2;
    xspeed=0;
  }

    //reverse X direction until it hits the 200X edge
  if(xpos < 0 && ypos ==80){
    directionX = 1;
    yspeed = 0;
    xspeed =2;
  }

      //move down 10 steps
      if (xpos > width-size && ypos ==80) { //down
    directionY=1;
    yspeed =2;
    xspeed=0;
  }

        //reverse X direction until it hits the 0X edge
  if(xpos>width-size && ypos ==100){
    directionX = -1;
    yspeed = 0;
    xspeed =2;
  }
         //move down 10 steps
 if (xpos < 0 && ypos ==100) { //down
    directionY=1;
    yspeed =2;
    xspeed=0;
  }
    //reverse X direction until it hiths the 200X edge
        if (xpos < 0 && ypos ==120) { //down
    directionX=1;
    yspeed =0;
    xspeed=2;
  }

  //move down 10 steps
   if (xpos > width-size && ypos ==120) {
    directionY=1;
    yspeed =2;
    xspeed=0;
   }
   //reverse direction until it hits teh 0X edge
    if (xpos > width-size && ypos ==140) {
    directionX=-1;
    yspeed =0;
    xspeed=2;
    }
    //move down 10 steps
         if (xpos < 0 && ypos ==140) { //down
    directionY=1;
    yspeed =2;
    xspeed=0;
         }
    //reverse X direction until it hiths the 200X edge

   if (xpos < 0 && ypos ==160) { //down
    directionX=1;
    yspeed =0;
    xspeed=2;
         }
    //move down 10 steps
       if (xpos > width-size && ypos ==160) {
    directionY=1;
    yspeed =2;
    xspeed=0;
   }
    //reverse direction until it hits teh 200X edge
       if (xpos > width-size && ypos ==180) {
    directionX=-1;
    yspeed =0;
    xspeed=2;
    }
       //move down 10 steps
       if (xpos > 0 && ypos ==180) {
    directionY=1;
    yspeed =2;
    xspeed=0;
   }
      //reverse direction until it hits teh 200x edge
       if (xpos > 0 && ypos ==200) {
    directionX=1;
    yspeed =0;
    xspeed=2;
    }

  //TELL ARDUINO WHICH WAY TO SEND MOTORS

    if (directionX >= 0){
    arduino.digitalWrite(ledPin, Arduino.HIGH);             
    arduino.digitalWrite(XdirPin, Arduino.HIGH);
      }
      else{
        arduino.digitalWrite(ledPin, Arduino.LOW);             
        arduino.digitalWrite(XdirPin, Arduino.LOW);
       }

  if (directionY >= 0){
    //arduino.digitalWrite(ledPin, Arduino.HIGH);             
    arduino.digitalWrite(YdirPin, Arduino.HIGH);
      }
      else{
        //arduino.digitalWrite(ledPin, Arduino.LOW);             
        arduino.digitalWrite(YdirPin, Arduino.LOW);
       }
   if (xspeed == 0) {            
    arduino.digitalWrite(XenablePin, Arduino.HIGH);
      }
      else{            
        arduino.digitalWrite(XenablePin, Arduino.LOW);
       }

    if (yspeed == 0) {            
     arduino.digitalWrite(YenablePin, Arduino.HIGH);
      }
      else{            
        arduino.digitalWrite(YenablePin, Arduino.LOW);
       }


  // Draw the shape
  ellipse(xpos+size/2, ypos+size/2, size, size);

}

Step 16: Pinch Wheel Extruder

If have looked at the reprap.org site, you'll notice that the plastic extruder is very important to making a 3D print.  They've come up with a nice looking "pinch wheel" extruder.  I've built one based on the discriptions here (http://builders.reprap.org/search?q=pinch+wheel ).

This includes a stepper motor.  I am driving it with an "EasyDriver" I bought from SparkFun.  It is EasyDriver V4 co-designed with Brian Schmalz.  It has breakouts for microstepping and does not get too hot.

http://www.sparkfun.com/commerce/product_info.php?products_id=9402.

Here are some images of the extruder.   If anyone is intersted I can post a template for the layout.




Step 17: Extruder Temp Control and Code

Description:
To get a usable stream of melted plastic out of the extruder, the tempurature has to be hot enough to melt the plastic, but not so hot that it starts to smoke and burn.  You also only want to drive the stock material while the temp is within this range.

Arduino code (this is just a modifed version of some RepRap code).  This allows you to set a temperature range and then only runs the extruder motor when the heater within range. 

As shown below, the Raw tempurate reading is used.  Actual temp can also be used. 

//////////////////Arduino Code///////////////////
//this example  keeps temp above melting point of HDPE - but not too hot
//turns off stepper if temp is too low [NOTE: using EasyDriver board, pull enable pin HIGH to turn off
//turn heat off if too hot
//turn heat way up if too cold
//turn heat to medium if

//webpage http://dev.www.reprap.org/bin/view/Main/Temperature_Sensor_1_1

// Thermistor lookup table for RepRap Temperature Sensor Boards (http://make.rrrf.org/ts)
// Made with createTemperatureLookup.py (http://svn.reprap.org/trunk/reprap/firmware/Arduino/utilities/createTemperatureLookup.py)
// ./createTemperatureLookup.py --r0=100000 --t0=25 --r1=0 --r2=4700 --beta=4066 --max-adc=1023

#define THERMISTOR_PIN 0
#define heatPin 11        //heat level
#define EstepPin 5     //set extruder stepper to pin12
#define EdirPin 6      //set step direction to stepper pin11
#define EenablePin 12    //


byte lowTemp = 245;  // >>> if below lowTemp then extruder is disabled  - degF
byte minTemp = 245;  //>>>> SET MIN TEMP HERE  >>>>>>  - degF
byte maxTemp = 250;  //>>>> SET MAX TEMP HERE  >>>>>>  - degF
byte maxRaw = 125;
byte minRaw = 130;

byte cool = 0;   // heater off
byte warm = 255; //medium heat
byte hot = 255;  //heat up pretty high >> max would be 255, but I don't want to burn out the heater


// r0: 100000
// t0: 25
// r1: 0
// r2: 4700
// beta: 4066
// max adc: 1023
#define NUMTEMPS 20
short temptable[NUMTEMPS][2] = {
   {1, 841},
   {54, 255},
   {107, 209},
   {160, 184},
   {213, 166},
   {266, 153},
   {319, 142},
   {372, 132},
   {425, 124},
   {478, 116},
   {531, 108},
   {584, 101},
   {637, 93},
   {690, 86},
   {743, 78},
   {796, 70},
   {849, 61},
   {902, 50},
   {955, 34},
   {1008, 3}
};

void setup()
{
   Serial.begin(9600);
   Serial.println("Starting temperature exerciser.");
   pinMode(heatPin, OUTPUT);
   pinMode(EstepPin, OUTPUT);
   pinMode(EdirPin, OUTPUT);
   pinMode(EenablePin, OUTPUT);

}

void loop()
{
   int rawvalue = analogRead(THERMISTOR_PIN);
   int celsius = read_temp();
   int fahrenheit = (((celsius * 9) / 5) + 32);

   Serial.print("Current temp: ");
   Serial.print(celsius);
   Serial.print("C / ");
   Serial.print(fahrenheit);
   Serial.println("F");

   Serial.print("Raw value: ");
   Serial.println(rawvalue);
   Serial.println(" ");

    //
    //control the extruder heater and stepper motor based on the temperature
   //

    if (rawvalue >= minRaw){ //if temp too low - turn stepper off
     analogWrite(heatPin, hot);   //if temp too low- turn heat to max
     digitalWrite(EenablePin,HIGH); //if temp too low - turn off the stepper
                                   //??? Stop everything if temp too low  ???
     }
  // if((fahrenheit >=lowTemp) && (fahrenheit <=minTemp)){ // if temp below range- LED slow blink
  //   analogWrite(heatPin, hot);  //if temp below range - turn extruder up to max
  //   digitalWrite(EenablePin,LOW); //if hot enough then turn on stepper
  //   }
  // if ((fahrenheit >= minTemp) && (fahrenheit <=maxTemp)){ //if temp in range - LED ON
  //   analogWrite(heatPin, warm);   //if temp is in range - keep extruder warm
  //   digitalWrite(EenablePin,LOW); //if hot enough then turn on stepper
  //   }

      if ((rawvalue <= minRaw)){ //if temp in range - LED ON
     analogWrite(heatPin, warm);   //if temp is in range - keep extruder warm
     digitalWrite(EenablePin,LOW); //if hot enough then turn on stepper
     }

   if(rawvalue <=maxRaw){   //if temp above range -LED fast blink
     analogWrite(heatPin, cool);  //if temp too high - turn heater off
     digitalWrite(EenablePin,LOW); //if hot enough then turn on stepper
     }
      //run extruder stepper motor
 digitalWrite(EdirPin,LOW);
 digitalWrite(EstepPin,HIGH);
 delayMicroseconds(2);
 digitalWrite(EstepPin,LOW);
 delay(15);

  // delay(1000);
}

int read_temp()
{
   int rawtemp = analogRead(THERMISTOR_PIN);
   int current_celsius = 0;

   byte i;
   for (i=1; i        if (temptable[i][0] > rawtemp)
      {
         int realtemp  = temptable[i-1][1] + (rawtemp - temptable[i-1][0]) * (temptable[i][1] - temptable[i-1][1]) / (temptable[i][0] - temptable[i-1][0]);

         if (realtemp > 255)
            realtemp = 255;

         current_celsius = realtemp;

         break;
      }
   }

   // Overflow: We just clamp to 0 degrees celsius
   if (i == NUMTEMPS)
   current_celsius = 0;

   return current_celsius;



}


Step 18: Second Round of Extruder Code

Here is a second pass at the extruder code - If the first doesn't work, then try this. 

///////////// Arduino Only///////////////////////


//////////////////Arduino Code///////////////////
//this example  keeps temp above melting point of HDPE - but not too hot
//turns off stepper if temp is too low [NOTE: using EasyDriver board, pull enable pin HIGH to turn off
//turn heat off if too hot
//turn heat way up if too cold
//turn heat to medium if

//webpage http://dev.www.reprap.org/bin/view/Main/Temperature_Sensor_1_1

// Thermistor lookup table for RepRap Temperature Sensor Boards (http://make.rrrf.org/ts)
// Made with createTemperatureLookup.py (http://svn.reprap.org/trunk/reprap/firmware/Arduino/utilities/createTemperatureLookup.py)
// ./createTemperatureLookup.py --r0=100000 --t0=25 --r1=0 --r2=4700 --beta=4066 --max-adc=1023

#define THERMISTOR_PIN 0
#define heatPin 11        //heat level
#define EstepPin 5     //set extruder stepper to pin12
#define EdirPin 6      //set step direction to stepper pin11
#define EenablePin 12    //


byte lowTemp = 175;  // >>> if below lowTemp then extruder is disabled  - degF
byte minTemp = 180;  //>>>> SET MIN TEMP HERE  >>>>>>  - degF
byte maxTemp = 185;  //>>>> SET MAX TEMP HERE  >>>>>>  - degF
byte maxRaw = 110;
byte minRaw = 120;

byte cool = 0;   // heater off
byte warm = 255; //medium heat
byte hot = 255;  //heat up pretty high >> max would be 255, but I don't want to burn out the heater


// r0: 100000
// t0: 25
// r1: 0
// r2: 4700
// beta: 4066
// max adc: 1023
#define NUMTEMPS 20
short temptable[NUMTEMPS][2] = {
   {1, 841},
   {54, 255},
   {107, 209},
   {160, 184},
   {213, 166},
   {266, 153},
   {319, 142},
   {372, 132},
   {425, 124},
   {478, 116},
   {531, 108},
   {584, 101},
   {637, 93},
   {690, 86},
   {743, 78},
   {796, 70},
   {849, 61},
   {902, 50},
   {955, 34},
   {1008, 3}
};

void setup()
{
   Serial.begin(9600);
   Serial.println("Starting temperature exerciser.");
   pinMode(heatPin, OUTPUT);
   pinMode(EstepPin, OUTPUT);
   pinMode(EdirPin, OUTPUT);
   pinMode(EenablePin, OUTPUT);

}

void loop()
{
   int rawvalue = analogRead(THERMISTOR_PIN);
   int celsius = read_temp();
   int fahrenheit = (((celsius * 9) / 5) + 32);

   Serial.print("Current temp: ");
   Serial.print(celsius);
   Serial.print("C / ");
   Serial.print(fahrenheit);
   Serial.println("F");

   Serial.print("Raw value: ");
   Serial.println(rawvalue);
   Serial.println(" ");

    //
    //control the extruder heater and stepper motor based on the temperature
   //

    if (rawvalue >= minRaw){ //if temp too low - turn stepper off
     analogWrite(heatPin, hot);   //if temp too low- turn heat to max
     digitalWrite(EenablePin,HIGH); //if temp too low - turn off the stepper
                                   //??? Stop everything if temp too low  ???
     }
  // if((fahrenheit >=lowTemp) && (fahrenheit <=minTemp)){ // if temp below range- LED slow blink
  //   analogWrite(heatPin, hot);  //if temp below range - turn extruder up to max
  //   digitalWrite(EenablePin,LOW); //if hot enough then turn on stepper
  //   }
  // if ((fahrenheit >= minTemp) && (fahrenheit <=maxTemp)){ //if temp in range - LED ON
  //   analogWrite(heatPin, warm);   //if temp is in range - keep extruder warm
  //   digitalWrite(EenablePin,LOW); //if hot enough then turn on stepper
  //   }

      if ((rawvalue <= minRaw)){ //if temp in range - LED ON
     analogWrite(heatPin, warm);   //if temp is in range - keep extruder warm
     digitalWrite(EenablePin,LOW); //if hot enough then turn on stepper
     }

   if(rawvalue<=maxRaw){   //if temp above range -LED fast blink
     analogWrite(heatPin, cool);  //if temp too high - turn heater off
     digitalWrite(EenablePin,LOW); //if hot enough then turn on stepper
     }
      //run extruder stepper motor
 digitalWrite(EdirPin,LOW);
 digitalWrite(EstepPin,HIGH);
 delayMicroseconds(2);
 digitalWrite(EstepPin,LOW);
 delay(1);

  // delay(1000);
}

int read_temp()
{
   int rawtemp = analogRead(THERMISTOR_PIN);
   int current_celsius = 0;

   byte i;
   for (i=1; i <NUMTEMPS; i++) {
      if (temptable[i][0] > rawtemp)
      {
         int realtemp  = temptable[i-1][1] + (rawtemp - temptable[i-1][0]) * (temptable[i][1] - temptable[i-1][1]) / (temptable[i][0] - temptable[i-1][0]);

         if (realtemp > 255)
            realtemp = 255;

         current_celsius = realtemp;

         break;
      }
   }

   // Overflow: We just clamp to 0 degrees celsius
   if (i == NUMTEMPS)
   current_celsius = 0;

   return current_celsius;

}

Step 19: Third Round of Extruder Code!


This bit of extruder conrol is working well with polylactic acid (PLA).

You can by some here if you are intersted: https://ultimachine.com/


//////////////////Arduino Code///////////////////
//
/*    EXTRUDER CONTROL
          WHAT IT DOES:
                -REGULATE TEMP VIA PWM
                -RUN STEPPER MOTOR OF PINCH WHEEL EXTRUDER WHEN IT IS WITHIN PROPER TEMP RANGE
                  -RUNNING STEPPER FROM EASYDRIVER BOARD

 */                
//Turns off stepper if temp is too low [NOTE: using EasyDriver board, pull enable pin HIGH to turn off
//turn heat off if too hot
//turn heat way up if too cold
//turn heat to medium if

//THIS IS BASED ON CODE AND DESIGNS FROM
    //webpage http://dev.www.reprap.org/bin/view/Main/Temperature_Sensor_1_1

// Thermistor lookup table for RepRap Temperature Sensor Boards (http://make.rrrf.org/ts)
// Made with createTemperatureLookup.py (http://svn.reprap.org/trunk/reprap/firmware/Arduino/utilities/createTemperatureLookup.py)
// ./createTemperatureLookup.py --r0=100000 --t0=25 --r1=0 --r2=4700 --beta=4066 --max-adc=1023

#define THERMISTOR_PIN 0
#define heatPin 11        //heat level
#define EstepPin 5     //set extruder stepper to pin12
#define EdirPin 6      //set step direction to stepper pin11
#define EenablePin 12    //
#define LED 13


byte lowTemp = 95;  // >>> if below lowTemp then extruder is disabled  - degF
byte minTemp = 100;  //>>>> SET MIN TEMP HERE  >>>>>>  - degF
byte maxTemp = 105;  //>>>> SET MAX TEMP HERE  >>>>>>  - degF
//byte maxRaw = 690;
//byte minRaw = 700;

byte cool = 0;   // heater off
byte warm = 255; //medium heat
byte hot = 255;  //heat up pretty high >> max would be 255, but I don't want to burn out the heater


// r0: 100000
// t0: 25
// r1: 0
// r2: 4700
// beta: 4066
// max adc: 1023
#define NUMTEMPS 20
short temptable[NUMTEMPS][2] = {
   {1, 841},
   {54, 255},
   {107, 209},
   {160, 184},
   {213, 166},
   {266, 153},
   {319, 142},
   {372, 132},
   {425, 124},
   {478, 116},
   {531, 108},
   {584, 101},
   {637, 93},
   {690, 86},
   {743, 78},
   {796, 70},
   {849, 61},
   {902, 50},
   {955, 34},
   {1008, 3}
};

void setup()
{
   Serial.begin(9600);
   Serial.println("Starting temperature exerciser.");
   pinMode(heatPin, OUTPUT);
   pinMode(EstepPin, OUTPUT);
   pinMode(EdirPin, OUTPUT);
   pinMode(EenablePin, OUTPUT);

}

void loop()
{
   int rawvalue = analogRead(THERMISTOR_PIN);
   int celsius = read_temp();
   int fahrenheit = (((celsius * 9) / 5) + 32);

   Serial.print("Current temp: ");
   Serial.print(celsius);
   Serial.print("C / ");
   Serial.print(fahrenheit);
   Serial.println("F");

   Serial.print("Raw value: ");
   Serial.println(rawvalue);
   Serial.println(" ");

    //
    //control the extruder heater and stepper motor based on the temperature
   //

    if (celsius <= minTemp){ //if temp too low - turn stepper off
     analogWrite(heatPin, hot);   //if temp too low- turn heat to max
     digitalWrite(EenablePin,HIGH); //if temp too low - turn off the stepper
     digitalWrite(LED,HIGH);
                                   //??? Stop everything if temp too low  ???
     }
  if((celsius >=lowTemp) && (celsius <=minTemp)){ // if temp below range- LED slow blink
    analogWrite(heatPin, hot);  //if temp below range - turn extruder up to max
    digitalWrite(EenablePin,LOW); //if hot enough then turn on stepper
    }
  if ((celsius >= minTemp) && (celsius<=maxTemp)){ //if temp in range - LED ON
     analogWrite(heatPin, warm);   //if temp is in range - keep extruder warm
    digitalWrite(EenablePin,LOW); //if hot enough then turn on stepper
     }

      //run extruder stepper motor
 digitalWrite(EdirPin,LOW);
 digitalWrite(EstepPin,HIGH);
 delayMicroseconds(2);
 digitalWrite(EstepPin,LOW);
 delay(1);

  // delay(1000);
}

int read_temp()
{
   int rawtemp = analogRead(THERMISTOR_PIN);
   int current_celsius = 0;

   byte i;
   for (i=1; i       if (temptable[i][0] > rawtemp)
      {
         int realtemp  = temptable[i-1][1] + (rawtemp - temptable[i-1][0]) * (temptable[i][1] - temptable[i-1][1]) / (temptable[i][0] - temptable[i-1][0]);

         if (realtemp > 255)
            realtemp = 255;

         current_celsius = realtemp;

         break;
      }
   }

   // Overflow: We just clamp to 0 degrees celsius
   if (i == NUMTEMPS)
   current_celsius = 0;

   return current_celsius;

}

Step 20: 3D Bouncing Ball - Processing


Here is some Processing code that shows a ball bouncing around in a 3D cube.

This is useful because it contains information for the X,Y and Z axiz.


It will be combined with the Firmata code in order to send the movements of all 3-axis to the Arduino, which in turn controlls the stepper motors, that move the platforms in each axis.  That code will then be combined with the "mesh" pattern from step 14 to create a 3D mesh.

As in step 6 - I've built this on some sample code that came packaged with Processing.  It is under Examples->Topics->Motion->Bounce

/////////////////// *********PROCESSING CODE ONLY*********

/**
 * Bounce_3D_0
 *
 * When the shape hits the edge of the window, it reverses its direction.
 *
 *Modified for 3D


 NOTE:  0,0,0   - top left corner (facing the computer monitor)
        negative Z axis points 'into' the computer monitor
        positive Y axis points down
        positive X axis points to the right
 */

int size = 40;       // Width of the shape
float xpos, ypos, zpos;    // Starting position of shape  
float depth;

float xspeed = 2.5;  // Speed of the shape
float yspeed = 2;  // Speed of the shape
float zspeed = 3;

int xdirection = 1;  // Left or Right
int ydirection = 1;  // Top to Bottom
int zdirection = 1;  //front or back


void setup()
{
  size(400, 400, P3D);
  noStroke();
  frameRate(30);
  smooth();
  // Set the starting position of the shape
  xpos = width/2;
  ypos = height/2;
  zpos = -height/2; //note that Zaxis goes 'into' the screen
  depth = -height;
}

void draw()
{
  background(102);
  lights(); 

//glass box                  //note: line(x1, y1, z1, x2, y2, z2)
stroke(255);
//back
line(0,0,depth,  width,0,depth);           
line(0,height,depth,  width,height,depth);
line(0,0,depth,  0,height,depth);
line(width,0,depth,  width,height,depth);
//corners
line(0,0,0,  0,0,depth);
line(0,height,0, 0,height,depth);
line(width,0,0,  width,0,depth);
line(width,height,0,  width,height,depth);


  // Update the position of the shape
  xpos = xpos + ( xspeed * xdirection );
  ypos = ypos + ( yspeed * ydirection );
  zpos = zpos + ( zspeed * zdirection );

  // Test to see if the shape exceeds the boundaries of the screen
  // If it does, reverse its direction by multiplying by -1


  if (xpos > width-size || xpos < 0) {
    xdirection *= -1;
  }
  if (ypos > height-size || ypos < 0) {
    ydirection *= -1;
  }

  if (zpos < -height-size || zpos > 0) {  //note that Zaxis goes 'into' the screen
    zdirection *= -1;
  }


  // Draw the shape

lights();
translate(xpos, ypos, zpos);

sphere(size);

}

Step 21: 3D - Follow the Bouncing Ball (this Includes Firmata)


Here is the 3D bouncing ball Processing  and Adruino code.

This will run X,Y,Z stepper motors.

The Arduino code follows, this is the  code from Step 13 with the Z axis added.


///////////////////////////////PROCESSING /////////////////////////////

 /////////////////// *********PROCESSING with FIRMATA*********

/**
 * Bounce_3D_0
 *
 * When the shape hits a boundry it reverses its direction.
 There are X,Y, Z bounds

 Direction is outputed -

     Processsing -> Firmata -> Arduino -> Drivers -> Steppers
 *
 *Modified for 3D


 NOTE:  0,0,0   - top left corner (facing the computer monitor)
        negative Z axis points 'into' the computer monitor
        positive Y axis points down
        positive X axis points to the right
 */

 import processing.serial.*;
import cc.arduino.*;

Arduino arduino;

//Serial myPort;  // Create object from Serial class
      // Data received from the serial port
int ledPin = 13;
int XstepPin = 10;
int XdirPin = 7;
int YstepPin = 2;
int YdirPin = 3;
int ZstepPin = 19;
int ZdirPin = 18;

int size = 40;       // Width of the shape
float xpos, ypos, zpos;    // Starting position of shape  
float depth;

float xspeed = 2.5;  // Speed of the shape
float yspeed = 2;  // Speed of the shape
float zspeed = 3;

int xdirection = 1;  // Left or Right
int ydirection = 1;  // Top to Bottom
int zdirection = 1;  //front or back


void setup()
{
  size(200, 200, P3D);
  noStroke();
  frameRate(30);
  smooth();
  // Set the starting position of the shape
  xpos = width/2;
  ypos = height/2;
  zpos = -height/2; //note that Zaxis goes 'into' the screen
  depth = -height;

    //setup communication with Arduino
  arduino = new Arduino(this, Arduino.list()[0], 57600); // v1
  arduino.pinMode(ledPin, Arduino.OUTPUT);
  arduino.pinMode(XstepPin, Arduino.OUTPUT);
  arduino.pinMode(XdirPin, Arduino.OUTPUT);
  arduino.pinMode(YstepPin, Arduino.OUTPUT);
  arduino.pinMode(YdirPin, Arduino.OUTPUT);
  arduino.pinMode(ZstepPin, Arduino.OUTPUT);
  arduino.pinMode(ZdirPin, Arduino.OUTPUT);
}

void draw()
{
  background(102);
  lights(); 

//glass box                  //note: line(x1, y1, z1, x2, y2, z2)
stroke(255);
//back
line(0,0,depth,  width,0,depth);           
line(0,height,depth,  width,height,depth);
line(0,0,depth,  0,height,depth);
line(width,0,depth,  width,height,depth);
//corners
line(0,0,0,  0,0,depth);
line(0,height,0, 0,height,depth);
line(width,0,0,  width,0,depth);
line(width,height,0,  width,height,depth);


  // Update the position of the shape
  xpos = xpos + ( xspeed * xdirection );
  ypos = ypos + ( yspeed * ydirection );
  zpos = zpos + ( zspeed * zdirection );

  // Test to see if the shape exceeds the boundaries of the screen
  // If it does, reverse its direction by multiplying by -1


  if (xpos > width-size || xpos < 0) {
    xdirection *= -1;
  }
  if (ypos > height-size || ypos < 0) {
    ydirection *= -1;
  }

  if (zpos < -height-size || zpos > 0) {  //note that Zaxis goes 'into' the screen
    zdirection *= -1;
  }

  // Draw the shape

lights();
translate(xpos, ypos, zpos);

sphere(size);


  // CONTROLL THE STEPPER MOTORS

    //  X
  if (xdirection >= 0){
    arduino.digitalWrite(ledPin, Arduino.HIGH);             
    arduino.digitalWrite(XdirPin, Arduino.HIGH);
    arduino.digitalWrite(ZdirPin, Arduino.HIGH);
      }
      else{
        arduino.digitalWrite(ledPin, Arduino.LOW);             
        arduino.digitalWrite(XdirPin, Arduino.LOW);
        arduino.digitalWrite(ZdirPin, Arduino.LOW);
       }

     //  Y 
  if (ydirection >= 0){              
    arduino.digitalWrite(YdirPin, Arduino.HIGH);
      }
      else{          
        arduino.digitalWrite(YdirPin, Arduino.LOW);
       }
     //  Z   
if (zdirection >= 0){             
    arduino.digitalWrite(ZdirPin, Arduino.HIGH);
      }
      else{           
        arduino.digitalWrite(ZdirPin, Arduino.LOW);
       }
}




/////////////////////////////ARDUINO////////////////////////////////////////

// Wiring/Arduino code:// simmple digital firmata
  //Supports as many digital inputs and outputs as possible.

  //This example code is in the public domain.

#include

#define XstepPin 10
#define XdirPin 7

#define YstepPin 2
#define YdirPin 3

#define ZstepPin 19
#define ZdirPin  18

byte previousPIN[2];  // PIN means PORT for input
byte previousPORT[2];

void outputPort(byte portNumber, byte portValue)
{
// only send the data when it changes, otherwise you get too many messages!
    if(previousPIN[portNumber] != portValue) {
        Firmata.sendDigitalPort(portNumber, portValue);
        previousPIN[portNumber] = portValue;
        Firmata.sendDigitalPort(portNumber, portValue);
    }
}

void setPinModeCallback(byte pin, int mode) {
    if(pin > 1) { // don't touch RxTx pins (0,1)
        pinMode(pin, mode);
    }
}

void digitalWriteCallback(byte port, int value)
{
    byte i;
    byte currentPinValue, previousPinValue;

    if(value != previousPORT[port]) {
        for(i=0; i<8; i++) {
            currentPinValue = (byte) value & (1 << i);
            previousPinValue = previousPORT[port] & (1 << i);
            if(currentPinValue != previousPinValue) {
                digitalWrite(i + (port*8), currentPinValue);
            }
        }
        previousPORT[port] = value;
    }
}

void setup()
{
    Firmata.setFirmwareVersion(0, 1);
    Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
    Firmata.attach(SET_PIN_MODE, setPinModeCallback);
    Firmata.begin(57600);
}

void loop()
{
    outputPort(0, PIND &~ B00000011); // pins 0-7, ignoring Rx/Tx pins (0/1)
    outputPort(1, PINB); // pins 8-13
    while(Firmata.available()) {
        Firmata.processInput();
    }

//added stepper sequence to firmata code
digitalWrite(XstepPin,HIGH);    //take steps
digitalWrite(YstepPin,HIGH);
digitalWrite(ZstepPin,HIGH);
delayMicroseconds(2);
digitalWrite(XstepPin,LOW);
digitalWrite(YstepPin,LOW);
digitalWrite(ZstepPin,LOW);
delayMicroseconds(2);
delayMicroseconds(1000); //  <<<<<< USE TO CHANGE STEPPER SPEED???? <<<<<<<<


}


Step 22: Doing to Things at Once

So far we have been building two sets of code:

1: to controll  the X,Y,Z axis
2: to control the extruder temperature and motor

The trick now, is to run both at once.  The problem is that the extruder motor must be run at a much slower rate then the X,Y,Z motors.  In order to run the steppers at different speeds you need a timer or counter, or something.  I'm going to make it so that for every so many X,Y,Z steps, the extruder motor takes one step.

Here is  a very simple bit of code that does this.  This is based on an example that was included in the Processing dowload.  The orgingal code ran a line across the screen, moving one position for every loop through the program.  I've added a parameter called "timer" that coundt up to 4, then changes teh background to white, then resets to 0 and starts counting again. 

So what you get is two things running at once at a rate of 4:1.


Here is the processing code:


///////////////////////////PROCESSING ONLY//////////////////////////////////

void setup() {
  frameRate(4);
}
int pos = 0;
int timer= 0;
void draw() {
  background(204);
  pos++;
  line(pos, 20, pos, 80);
  if(pos > width) {
    pos = 0;
  }
  timer++;                         //INCREMENT TIMER
  if (timer ==4){               // DO SOMETHING AFTER 4 COUNTS
    background(255);       //SOMETHING
    timer = 0;                    //RESET THE TIMER
  }
}

Step 23: Better Mesh (in Progress)

here is  mesh drawing code, that used less specific coordinates

///////////////////Processing/////////////
/**

 *Point moves back and forth accross the screen  - includes movement in the X direction


 ****uses different variables to indicate that this is in progress
      (and because I forgot what variables I was using)

 */

int res = 50;    //print resolution

int a = 100;
int b = 1;
int dir_a = 1;
int dir_b = 0;
int step_a = 1;
int step_b = 0;
int old_b = 0;
int next_b = res;

void setup()
{
  size(640, 200);
  stroke(255);
  background(50);
}

void draw()

{

a = a + dir_a*step_a;
b = b + dir_b*step_b;

  if ((a < 10 || a > height-10) && b < next_b) {
    dir_b = 1;
    step_a = 0;
    step_b = 1;
    dir_a = (-1)*dir_a;
    old_b = b;
  }
  else {
    step_a=1;
    step_b=0;
    next_b = old_b+res; 
  }

  point(b, a);  // Syntax point(x1, y1)

  print(b);
  print(',');
  println(a);

}

Step 24: Continous Mesh Rotating 90deg Each Layer

This shows a point continously tracing mesh pattern across an X,Y plane. 

The mesh is rotatated 90deg after each layer is traced.

This can be used to output X,Y directions to the stepper motors.

Z axis control can be added to this.


///////////////////Processing/////////////
/**

 *Point moves back and forth accross the screen  - includes movement in the X and Y direction

 Repeats over and over, rotating 90deg every time a layer is complete

 takes some odd steps at the begining


 ****uses different variables to indicate that this is in progress
      (and because I forgot what variables I was using)

 */

int res = 50;    //print resolution

int a = 10;
int b = 10;
int dir_a = 1;
int dir_b = 1;
int step_a = 1;
int step_b = 0;
int old_step_a = 1;
int old_step_b =0;

int old_dir_a = 1;
int old_dir_b = 0;

int dir_switch = 0;
int old_dir_switch = 0;

int old_a = 0;
int old_b = 0;
int next_b = res;
int next_a = res;

void setup()
{
  size(200, 200);
  stroke(255);
  background(50);
}

void draw()
{

    background(50);
if ((a < 10 || a > height - 10) && old_step_b ==0){
  dir_a = -1 * dir_a;
  next_b = b+res;
  dir_switch = 1;
}

if ((old_dir_switch != dir_switch) && b < next_b){
  step_a = 0;
  step_b = 1;
  dir_switch = 0;
}

if (b > next_b){
  step_a = 1;
  step_b = 0;
  next_b = b+res;
  dir_switch = 0;
}

if ((b < 10 || b > width - 10) && old_step_a ==0){
  dir_b = -1 * dir_b;
  next_a = a + res;
  dir_switch = 1;
}

 if ((old_dir_switch != dir_switch) && a < next_a){
  step_b = 0;
  step_a = 1;
  dir_switch = 0;
}

if (a > next_a){
  step_b = 1;
  step_a = 0;
  next_a = a + res;
  dir_switch = 0;
}

// calculate postion
a = a + dir_a*step_a;
b = b + dir_b*step_b;
//display point
point(b, a);  // Syntax point(x1, y1)

//store some values as old for comparison
old_a = a;
old_b = b;
old_step_a = step_a;
old_step_b = step_b;
old_dir_a = dir_a;
old_dir_b = dir_b;
old_dir_switch = old_dir_switch + dir_switch;

  print(b);
  print(',');
  println(a);

}

Step 25: Prints Using Reprap Gcode Interpreter and Host Software


Arduino Contest

First Prize in the
Arduino Contest