├── arduino_libraries ├── AFMotorDrawbot │ ├── README.txt │ ├── keywords.txt │ ├── examples │ │ ├── AFMotor_ConstantSpeed │ │ │ └── AFMotor_ConstantSpeed.pde │ │ ├── MotorTest │ │ │ └── MotorTest.pde │ │ ├── StepperTest │ │ │ └── StepperTest.pde │ │ ├── MotorParty │ │ │ └── MotorParty.pde │ │ └── AFMotor_MultiStepper │ │ │ └── AFMotor_MultiStepper.pde │ ├── AFMotorDrawbot.h │ └── AFMotorDrawbot.cpp ├── HG7881Step │ ├── README.txt │ ├── keywords.txt │ ├── HG7881Step.h │ └── HG7881Step.cpp └── Adafruit_MotorShield │ ├── README.txt │ ├── keywords.txt │ ├── license.txt │ ├── utility │ ├── license.txt │ ├── Adafruit_PWMServoDriver.h │ └── Adafruit_PWMServoDriver.cpp │ ├── examples │ ├── StepperTest │ │ └── StepperTest.ino │ ├── Accel_ConstantSpeed │ │ └── Accel_ConstantSpeed.ino │ ├── DCMotorTest │ │ └── DCMotorTest.ino │ ├── StackingTest │ │ └── StackingTest.ino │ ├── MotorParty │ │ └── MotorParty.ino │ └── Accel_MultiStepper │ │ └── Accel_MultiStepper.ino │ ├── Adafruit_MotorShield.h │ └── Adafruit_MotorShield.cpp ├── README.txt ├── .gitattributes ├── GcodeCNCDemo2Axis ├── ams1.ino ├── HG7881.ino ├── PassThroughStep.ino ├── config.h ├── RAMPS.ino ├── CNCV3.ino ├── ams2.ino └── GcodeCNCDemo2Axis.ino ├── .gitignore ├── GcodeCNCDemo4AxisRAMPS └── GcodeCNCDemo4AxisRAMPS.ino ├── GcodeCNCDemo4AxisCNCShield └── GcodeCNCDemo4AxisCNCShield.ino ├── GcodeCNCDemo6AxisV2 └── GcodeCNCDemo6AxisV2.ino ├── GcodeCNCDemo4axisV2 └── GcodeCNCDemo4AxisV2.ino ├── GcodeCNCDemo6AxisRumba └── GcodeCNCDemo6AxisRumba.ino └── GcodeCNCDemo6AxisRumbaTimerInterrupt └── GcodeCNCDemo6AxisRumbaTimerInterrupt.ino /arduino_libraries/AFMotorDrawbot/README.txt: -------------------------------------------------------------------------------- 1 | This is the August 12, 2009 Adafruit Motor shield firmware with basic Microstepping support. Works with all Arduinos and the Mega 2 | 3 | For more information on the shield, please visit http://www.ladyada.net/make/mshield/ 4 | 5 | To install, click DOWNLOAD SOURCE in the top right corner, and see our tutorial at http://www.ladyada.net/library/arduino/libraries.html on Arduino Library installation -------------------------------------------------------------------------------- /arduino_libraries/HG7881Step/README.txt: -------------------------------------------------------------------------------- 1 | # Arduino Library for HG7881 (L9110) H-bridges to works with GCodeCNCDemo 2 | 3 | This is a Stepper library for use with HG7881 or L9110 H-bridges. 4 | 5 | Because these chips have poor thermal management and thus overheat easily. 6 | 7 | This library can handle the problem, they are not put into idle mode after stepping (and keep needlessly drawing huge amounts of current). 8 | 9 | Idle mode is when inputs A and B are either both HIGH or both LOW. This wrapper drives them both LOW after stepping. 10 | 11 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | GcodeCNCDemo 2 | 3 | These programs will teach an Arduino to listen to Gcode and move stepper motors. 4 | It is an easy way to program your Arduino CNC machine. 5 | 6 | For installation instructions, see 7 | http://learn.marginallyclever.com/index.php/GcodeCNCDemo#Installation 8 | 9 | For documentation, see 10 | http://learn.marginallyclever.com/index.php/GcodeCNCDemo 11 | 12 | Please visit the author's website - http://marginallyclever.com 13 | 14 | Dan Royer 15 | 2013-08-30 16 | 17 | This file was downloaded from http://www.github.com/MarginallyClever/GcodeCNCDemo -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /arduino_libraries/HG7881Step/keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For HG7881Step 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | HG7881 KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | onestep KEYWORD2 16 | release KEYWORD2 17 | 18 | ####################################### 19 | # Constants (LITERAL1) 20 | ####################################### 21 | 22 | MICROSTEPS LITERAL1 23 | FORWARD LITERAL1 24 | -------------------------------------------------------------------------------- /arduino_libraries/Adafruit_MotorShield/README.txt: -------------------------------------------------------------------------------- 1 | This is the library for the Adafruit Motor Shield V2 for Arduino. 2 | It supports DC motors & Stepper motors with microstepping as well 3 | as stacking-support. It is *not* compatible with the V1 library! 4 | 5 | It will only work with https://www.adafruit.com/products/1483 6 | 7 | Adafruit invests time and resources providing this open 8 | source code, please support Adafruit and open-source hardware 9 | by purchasing products from Adafruit! 10 | 11 | Written by Limor Fried/Ladyada for Adafruit Industries. 12 | BSD license, check license.txt for more information. 13 | All text above must be included in any redistribution. 14 | -------------------------------------------------------------------------------- /arduino_libraries/AFMotorDrawbot/keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map for AFMotor 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | AF_DCMotor KEYWORD1 10 | AF_Stepper KEYWORD1 11 | 12 | ####################################### 13 | # Methods and Functions (KEYWORD2) 14 | ####################################### 15 | 16 | enable KEYWORD2 17 | run KEYWORD2 18 | setSpeed KEYWORD2 19 | step KEYWORD2 20 | onestep KEYWORD2 21 | release KEYWORD2 22 | 23 | ####################################### 24 | # Constants (LITERAL1) 25 | ####################################### 26 | 27 | MICROSTEPPING LITERAL1 28 | FORWARD LITERAL1 29 | BACKWARD LITERAL1 30 | BRAKE LITERAL1 31 | RELEASE LITERAL1 32 | SINGLE LITERAL1 33 | DOUBLE LITERAL1 34 | INTERLEAVE LITERAL1 35 | MICROSTEP LITERAL1 -------------------------------------------------------------------------------- /arduino_libraries/Adafruit_MotorShield/keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map for AFMotor 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | AF_DCMotor KEYWORD1 10 | AF_Stepper KEYWORD1 11 | 12 | ####################################### 13 | # Methods and Functions (KEYWORD2) 14 | ####################################### 15 | 16 | enable KEYWORD2 17 | run KEYWORD2 18 | setSpeed KEYWORD2 19 | step KEYWORD2 20 | onestep KEYWORD2 21 | release KEYWORD2 22 | 23 | ####################################### 24 | # Constants (LITERAL1) 25 | ####################################### 26 | 27 | MICROSTEPPING LITERAL1 28 | FORWARD LITERAL1 29 | BACKWARD LITERAL1 30 | BRAKE LITERAL1 31 | RELEASE LITERAL1 32 | SINGLE LITERAL1 33 | DOUBLE LITERAL1 34 | INTERLEAVE LITERAL1 35 | MICROSTEP LITERAL1 -------------------------------------------------------------------------------- /arduino_libraries/AFMotorDrawbot/examples/AFMotor_ConstantSpeed/AFMotor_ConstantSpeed.pde: -------------------------------------------------------------------------------- 1 | // ConstantSpeed.pde 2 | // -*- mode: C++ -*- 3 | // 4 | // Shows how to run AccelStepper in the simplest, 5 | // fixed speed mode with no accelerations 6 | // Requires the AFMotor library (https://github.com/adafruit/Adafruit-Motor-Shield-library) 7 | // And AccelStepper with AFMotor support (https://github.com/adafruit/AccelStepper) 8 | // Public domain! 9 | 10 | #include 11 | #include 12 | 13 | AF_Stepper motor1(200, 1); 14 | 15 | 16 | // you can change these to DOUBLE or INTERLEAVE or MICROSTEP! 17 | void forwardstep() { 18 | motor1.onestep(FORWARD, SINGLE); 19 | } 20 | void backwardstep() { 21 | motor1.onestep(BACKWARD, SINGLE); 22 | } 23 | 24 | AccelStepper stepper(forwardstep, backwardstep); // use functions to step 25 | 26 | void setup() 27 | { 28 | Serial.begin(9600); // set up Serial library at 9600 bps 29 | Serial.println("Stepper test!"); 30 | 31 | stepper.setSpeed(50); 32 | } 33 | 34 | void loop() 35 | { 36 | stepper.runSpeed(); 37 | } 38 | -------------------------------------------------------------------------------- /arduino_libraries/AFMotorDrawbot/examples/MotorTest/MotorTest.pde: -------------------------------------------------------------------------------- 1 | // Adafruit Motor shield library 2 | // copyright Adafruit Industries LLC, 2009 3 | // this code is public domain, enjoy! 4 | 5 | #include 6 | 7 | AF_DCMotor motor(4); 8 | 9 | void setup() { 10 | Serial.begin(9600); // set up Serial library at 9600 bps 11 | Serial.println("Motor test!"); 12 | 13 | // turn on motor 14 | motor.setSpeed(200); 15 | 16 | motor.run(RELEASE); 17 | } 18 | 19 | void loop() { 20 | uint8_t i; 21 | 22 | Serial.print("tick"); 23 | 24 | motor.run(FORWARD); 25 | for (i=0; i<255; i++) { 26 | motor.setSpeed(i); 27 | delay(10); 28 | } 29 | 30 | for (i=255; i!=0; i--) { 31 | motor.setSpeed(i); 32 | delay(10); 33 | } 34 | 35 | Serial.print("tock"); 36 | 37 | motor.run(BACKWARD); 38 | for (i=0; i<255; i++) { 39 | motor.setSpeed(i); 40 | delay(10); 41 | } 42 | 43 | for (i=255; i!=0; i--) { 44 | motor.setSpeed(i); 45 | delay(10); 46 | } 47 | 48 | 49 | Serial.print("tech"); 50 | motor.run(RELEASE); 51 | delay(1000); 52 | } 53 | -------------------------------------------------------------------------------- /arduino_libraries/AFMotorDrawbot/examples/StepperTest/StepperTest.pde: -------------------------------------------------------------------------------- 1 | // Adafruit Motor shield library 2 | // copyright Adafruit Industries LLC, 2009 3 | // this code is public domain, enjoy! 4 | 5 | #include 6 | 7 | // Connect a stepper motor with 48 steps per revolution (7.5 degree) 8 | // to motor port #2 (M3 and M4) 9 | AF_Stepper motor(48, 2); 10 | 11 | void setup() { 12 | Serial.begin(9600); // set up Serial library at 9600 bps 13 | Serial.println("Stepper test!"); 14 | 15 | motor.setSpeed(10); // 10 rpm 16 | } 17 | 18 | void loop() { 19 | Serial.println("Single coil steps"); 20 | motor.step(100, FORWARD, SINGLE); 21 | motor.step(100, BACKWARD, SINGLE); 22 | 23 | Serial.println("Double coil steps"); 24 | motor.step(100, FORWARD, DOUBLE); 25 | motor.step(100, BACKWARD, DOUBLE); 26 | 27 | Serial.println("Interleave coil steps"); 28 | motor.step(100, FORWARD, INTERLEAVE); 29 | motor.step(100, BACKWARD, INTERLEAVE); 30 | 31 | Serial.println("Micrsostep steps"); 32 | motor.step(100, FORWARD, MICROSTEP); 33 | motor.step(100, BACKWARD, MICROSTEP); 34 | } 35 | -------------------------------------------------------------------------------- /arduino_libraries/HG7881Step/HG7881Step.h: -------------------------------------------------------------------------------- 1 | /* 2 | * HG7881 Stepper driver for GCodeCNCDemo 3 | 4 | * HG7881Step.h 5 | * 1/8 step for HG7881 6 | * by Luqman Sahidin, 2015 7 | 8 | The sequence of control signals for 4 control wires is as follows: 9 | 10 | Step C0 C1 C2 C3 11 | 1 1 0 1 0 \ 12 | 2 1 1 1 0 | 13 | 3 0 1 1 0 / 14 | 4 0 1 1 1 - 15 | 5 0 1 0 1 \ 16 | 6 1 1 0 1 | 17 | 7 1 0 0 1 / 18 | 8 1 0 1 1 - 19 | 20 | */ 21 | 22 | // ensure this library description is only included once 23 | #ifndef HG7881Step_h 24 | #define HG7881Step_h 25 | 26 | #define MICROSTEPS 16 // 8 or 16 27 | #define FORWARD 1 28 | 29 | // library interface description 30 | class HG7881Step { 31 | public: 32 | // constructors: 33 | HG7881Step(int number_of_steps, int motor_pin_1, int motor_pin_2, int motor_pin_3, int motor_pin_4); 34 | 35 | // mover method: 36 | void onestep(int dir); 37 | 38 | // release all coils 39 | void release(); 40 | 41 | private: 42 | // motor pin numbers: 43 | int pinA_IA; 44 | int pinA_IB; 45 | int pinB_IA; 46 | int pinB_IB; 47 | }; 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /arduino_libraries/AFMotorDrawbot/examples/MotorParty/MotorParty.pde: -------------------------------------------------------------------------------- 1 | // Adafruit Motor shield library 2 | // copyright Adafruit Industries LLC, 2009 3 | // this code is public domain, enjoy! 4 | 5 | #include 6 | #include 7 | 8 | // DC motor on M2 9 | AF_DCMotor motor(2); 10 | // DC hobby servo 11 | Servo servo1; 12 | // Stepper motor on M3+M4 48 steps per revolution 13 | AF_Stepper stepper(48, 2); 14 | 15 | void setup() { 16 | Serial.begin(9600); // set up Serial library at 9600 bps 17 | Serial.println("Motor party!"); 18 | 19 | // turn on servo 20 | servo1.attach(9); 21 | 22 | // turn on motor #2 23 | motor.setSpeed(200); 24 | motor.run(RELEASE); 25 | } 26 | 27 | int i; 28 | 29 | // Test the DC motor, stepper and servo ALL AT ONCE! 30 | void loop() { 31 | motor.run(FORWARD); 32 | for (i=0; i<255; i++) { 33 | servo1.write(i); 34 | motor.setSpeed(i); 35 | stepper.step(1, FORWARD, INTERLEAVE); 36 | delay(3); 37 | } 38 | 39 | for (i=255; i!=0; i--) { 40 | servo1.write(i-255); 41 | motor.setSpeed(i); 42 | stepper.step(1, BACKWARD, INTERLEAVE); 43 | delay(3); 44 | } 45 | 46 | motor.run(BACKWARD); 47 | for (i=0; i<255; i++) { 48 | servo1.write(i); 49 | motor.setSpeed(i); 50 | delay(3); 51 | stepper.step(1, FORWARD, DOUBLE); 52 | } 53 | 54 | for (i=255; i!=0; i--) { 55 | servo1.write(i-255); 56 | motor.setSpeed(i); 57 | stepper.step(1, BACKWARD, DOUBLE); 58 | delay(3); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /arduino_libraries/Adafruit_MotorShield/license.txt: -------------------------------------------------------------------------------- 1 | Software License Agreement (BSD License) 2 | 3 | Copyright (c) 2012, Adafruit Industries. All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 1. Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 3. Neither the name of the copyright holders nor the names of its 13 | contributors may be used to endorse or promote products derived from 14 | this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY 17 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /arduino_libraries/Adafruit_MotorShield/utility/license.txt: -------------------------------------------------------------------------------- 1 | Software License Agreement (BSD License) 2 | 3 | Copyright (c) 2012, Adafruit Industries 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of the copyright holders nor the 14 | names of its contributors may be used to endorse or promote products 15 | derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY 18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /arduino_libraries/AFMotorDrawbot/examples/AFMotor_MultiStepper/AFMotor_MultiStepper.pde: -------------------------------------------------------------------------------- 1 | // MultiStepper 2 | // -*- mode: C++ -*- 3 | // 4 | // Control both Stepper motors at the same time with different speeds 5 | // and accelerations. 6 | // Requires the AFMotor library (https://github.com/adafruit/Adafruit-Motor-Shield-library) 7 | // And AccelStepper with AFMotor support (https://github.com/adafruit/AccelStepper) 8 | // Public domain! 9 | 10 | #include 11 | #include 12 | 13 | // two stepper motors one on each port 14 | AF_Stepper motor1(200, 1); 15 | AF_Stepper motor2(200, 2); 16 | 17 | // you can change these to DOUBLE or INTERLEAVE or MICROSTEP! 18 | // wrappers for the first motor! 19 | void forwardstep1() { 20 | motor1.onestep(FORWARD, SINGLE); 21 | } 22 | void backwardstep1() { 23 | motor1.onestep(BACKWARD, SINGLE); 24 | } 25 | // wrappers for the second motor! 26 | void forwardstep2() { 27 | motor2.onestep(FORWARD, SINGLE); 28 | } 29 | void backwardstep2() { 30 | motor2.onestep(BACKWARD, SINGLE); 31 | } 32 | 33 | // Motor shield has two motor ports, now we'll wrap them in an AccelStepper object 34 | AccelStepper stepper1(forwardstep1, backwardstep1); 35 | AccelStepper stepper2(forwardstep2, backwardstep2); 36 | 37 | void setup() 38 | { 39 | stepper1.setMaxSpeed(200.0); 40 | stepper1.setAcceleration(100.0); 41 | stepper1.moveTo(24); 42 | 43 | stepper2.setMaxSpeed(300.0); 44 | stepper2.setAcceleration(100.0); 45 | stepper2.moveTo(1000000); 46 | 47 | } 48 | 49 | void loop() 50 | { 51 | // Change direction at the limits 52 | if (stepper1.distanceToGo() == 0) 53 | stepper1.moveTo(-stepper1.currentPosition()); 54 | stepper1.run(); 55 | stepper2.run(); 56 | } 57 | -------------------------------------------------------------------------------- /arduino_libraries/AFMotorDrawbot/AFMotorDrawbot.h: -------------------------------------------------------------------------------- 1 | #ifndef _AFMotorDrawbot_h_ 2 | #define _AFMotorDrawbot_h_ 3 | //------------------------------------------------------------------------------ 4 | // Adafruit Motor shield library, modified for Drawbot 5 | // copyright Dan Royer, 2012 6 | // this code is public domain, enjoy! 7 | //------------------------------------------------------------------------------ 8 | 9 | #include 10 | #include 11 | 12 | //------------------------------------------------------------------------------ 13 | 14 | //#define MOTORDEBUG 1 15 | 16 | #define MICROSTEPS 16 // 8 or 16 17 | 18 | #define MOTOR1_A 2 19 | #define MOTOR1_B 3 20 | #define MOTOR2_A 1 21 | #define MOTOR2_B 4 22 | #define MOTOR4_A 0 23 | #define MOTOR4_B 6 24 | #define MOTOR3_A 5 25 | #define MOTOR3_B 7 26 | 27 | #define FORWARD 1 28 | #define BACKWARD 2 29 | #define BRAKE 3 30 | #define RELEASE 4 31 | 32 | // Arduino pin names 33 | #define MOTORLATCH 12 34 | #define MOTORCLK 4 35 | #define MOTORENABLE 7 36 | #define MOTORDATA 8 37 | 38 | //------------------------------------------------------------------------------ 39 | 40 | class AFMotorController { 41 | public: 42 | AFMotorController(); 43 | void enable(); 44 | friend class AF_DCMotor; 45 | void latch_tx(); 46 | }; 47 | 48 | 49 | class AF_Stepper { 50 | public: 51 | AF_Stepper(uint16_t, uint8_t); 52 | void step(uint16_t steps, uint8_t dir); 53 | void setSpeed(uint16_t); 54 | uint8_t onestep(uint8_t dir); 55 | void release(); 56 | uint16_t revsteps; // # steps per revolution 57 | uint8_t steppernum; 58 | uint32_t usperstep, steppingcounter; 59 | private: 60 | uint8_t currentstep; 61 | uint8_t a, b, c, d; 62 | }; 63 | 64 | //------------------------------------------------------------------------------ 65 | #endif -------------------------------------------------------------------------------- /arduino_libraries/Adafruit_MotorShield/examples/StepperTest/StepperTest.ino: -------------------------------------------------------------------------------- 1 | /* 2 | This is a test sketch for the Adafruit assembled Motor Shield for Arduino v2 3 | It won't work with v1.x motor shields! Only for the v2's with built in PWM 4 | control 5 | 6 | For use with the Adafruit Motor Shield v2 7 | ----> http://www.adafruit.com/products/1438 8 | */ 9 | 10 | 11 | #include 12 | #include 13 | #include "utility/Adafruit_PWMServoDriver.h" 14 | 15 | // Create the motor shield object with the default I2C address 16 | Adafruit_MotorShield AFMS = Adafruit_MotorShield(); 17 | // Or, create it with a different I2C address (say for stacking) 18 | // Adafruit_MotorShield AFMS = Adafruit_MotorShield(0x61); 19 | 20 | // Connect a stepper motor with 200 steps per revolution (1.8 degree) 21 | // to motor port #2 (M3 and M4) 22 | Adafruit_StepperMotor *myMotor = AFMS.getStepper(200, 2); 23 | 24 | 25 | void setup() { 26 | Serial.begin(9600); // set up Serial library at 9600 bps 27 | Serial.println("Stepper test!"); 28 | 29 | AFMS.begin(); // create with the default frequency 1.6KHz 30 | //AFMS.begin(1000); // OR with a different frequency, say 1KHz 31 | 32 | myMotor->setSpeed(10); // 10 rpm 33 | } 34 | 35 | void loop() { 36 | Serial.println("Single coil steps"); 37 | myMotor->step(100, FORWARD, SINGLE); 38 | myMotor->step(100, BACKWARD, SINGLE); 39 | 40 | Serial.println("Double coil steps"); 41 | myMotor->step(100, FORWARD, DOUBLE); 42 | myMotor->step(100, BACKWARD, DOUBLE); 43 | 44 | Serial.println("Interleave coil steps"); 45 | myMotor->step(100, FORWARD, INTERLEAVE); 46 | myMotor->step(100, BACKWARD, INTERLEAVE); 47 | 48 | Serial.println("Microstep steps"); 49 | myMotor->step(50, FORWARD, MICROSTEP); 50 | myMotor->step(50, BACKWARD, MICROSTEP); 51 | } -------------------------------------------------------------------------------- /arduino_libraries/Adafruit_MotorShield/utility/Adafruit_PWMServoDriver.h: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | This is a library for our Adafruit 16-channel PWM & Servo driver 3 | 4 | Pick one up today in the adafruit shop! 5 | ------> http://www.adafruit.com/products/815 6 | 7 | These displays use I2C to communicate, 2 pins are required to 8 | interface. For Arduino UNOs, thats SCL -> Analog 5, SDA -> Analog 4 9 | 10 | Adafruit invests time and resources providing this open source code, 11 | please support Adafruit and open-source hardware by purchasing 12 | products from Adafruit! 13 | 14 | Written by Limor Fried/Ladyada for Adafruit Industries. 15 | BSD license, all text above must be included in any redistribution 16 | ****************************************************/ 17 | 18 | #ifndef _ADAFRUIT_PWMServoDriver_H 19 | #define _ADAFRUIT_PWMServoDriver_H 20 | 21 | #if ARDUINO >= 100 22 | #include "Arduino.h" 23 | #else 24 | #include "WProgram.h" 25 | #endif 26 | 27 | 28 | #define PCA9685_SUBADR1 0x2 29 | #define PCA9685_SUBADR2 0x3 30 | #define PCA9685_SUBADR3 0x4 31 | 32 | #define PCA9685_MODE1 0x0 33 | #define PCA9685_PRESCALE 0xFE 34 | 35 | #define LED0_ON_L 0x6 36 | #define LED0_ON_H 0x7 37 | #define LED0_OFF_L 0x8 38 | #define LED0_OFF_H 0x9 39 | 40 | #define ALLLED_ON_L 0xFA 41 | #define ALLLED_ON_H 0xFB 42 | #define ALLLED_OFF_L 0xFC 43 | #define ALLLED_OFF_H 0xFD 44 | 45 | 46 | class Adafruit_PWMServoDriver { 47 | public: 48 | Adafruit_PWMServoDriver(uint8_t addr = 0x40); 49 | void begin(void); 50 | void reset(void); 51 | void setPWMFreq(float freq); 52 | void setPWM(uint8_t num, uint16_t on, uint16_t off); 53 | 54 | private: 55 | uint8_t _i2caddr; 56 | 57 | uint8_t read8(uint8_t addr); 58 | void write8(uint8_t addr, uint8_t d); 59 | }; 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /arduino_libraries/Adafruit_MotorShield/examples/Accel_ConstantSpeed/Accel_ConstantSpeed.ino: -------------------------------------------------------------------------------- 1 | // ConstantSpeed.pde 2 | // -*- mode: C++ -*- 3 | // 4 | // Shows how to run AccelStepper in the simplest, 5 | // fixed speed mode with no accelerations 6 | // Requires the Adafruit_Motorshield v2 library 7 | // https://github.com/adafruit/Adafruit_Motor_Shield_V2_Library 8 | // And AccelStepper with AFMotor support 9 | // https://github.com/adafruit/AccelStepper 10 | 11 | // This tutorial is for Adafruit Motorshield v2 only! 12 | // Will not work with v1 shields 13 | 14 | #include 15 | #include 16 | #include 17 | #include "utility/Adafruit_PWMServoDriver.h" 18 | 19 | // Create the motor shield object with the default I2C address 20 | Adafruit_MotorShield AFMS = Adafruit_MotorShield(); 21 | // Or, create it with a different I2C address (say for stacking) 22 | // Adafruit_MotorShield AFMS = Adafruit_MotorShield(0x61); 23 | 24 | // Connect a stepper motor with 200 steps per revolution (1.8 degree) 25 | // to motor port #2 (M3 and M4) 26 | Adafruit_StepperMotor *myStepper1 = AFMS.getStepper(200, 2); 27 | 28 | // you can change these to DOUBLE or INTERLEAVE or MICROSTEP! 29 | void forwardstep1() { 30 | myStepper1->onestep(FORWARD, SINGLE); 31 | } 32 | void backwardstep1() { 33 | myStepper1->onestep(BACKWARD, SINGLE); 34 | } 35 | 36 | AccelStepper Astepper1(forwardstep1, backwardstep1); // use functions to step 37 | 38 | void setup() 39 | { 40 | Serial.begin(9600); // set up Serial library at 9600 bps 41 | Serial.println("Stepper test!"); 42 | 43 | AFMS.begin(); // create with the default frequency 1.6KHz 44 | //AFMS.begin(1000); // OR with a different frequency, say 1KHz 45 | 46 | Astepper1.setSpeed(50); 47 | } 48 | 49 | void loop() 50 | { 51 | Astepper1.runSpeed(); 52 | } 53 | -------------------------------------------------------------------------------- /arduino_libraries/Adafruit_MotorShield/examples/DCMotorTest/DCMotorTest.ino: -------------------------------------------------------------------------------- 1 | /* 2 | This is a test sketch for the Adafruit assembled Motor Shield for Arduino v2 3 | It won't work with v1.x motor shields! Only for the v2's with built in PWM 4 | control 5 | 6 | For use with the Adafruit Motor Shield v2 7 | ----> http://www.adafruit.com/products/1438 8 | */ 9 | 10 | #include 11 | #include 12 | #include "utility/Adafruit_PWMServoDriver.h" 13 | 14 | // Create the motor shield object with the default I2C address 15 | Adafruit_MotorShield AFMS = Adafruit_MotorShield(); 16 | // Or, create it with a different I2C address (say for stacking) 17 | // Adafruit_MotorShield AFMS = Adafruit_MotorShield(0x61); 18 | 19 | // Select which 'port' M1, M2, M3 or M4. In this case, M1 20 | Adafruit_DCMotor *myMotor = AFMS.getMotor(1); 21 | // You can also make another motor on port M2 22 | //Adafruit_DCMotor *myOtherMotor = AFMS.getMotor(2); 23 | 24 | void setup() { 25 | Serial.begin(9600); // set up Serial library at 9600 bps 26 | Serial.println("Adafruit Motorshield v2 - DC Motor test!"); 27 | 28 | AFMS.begin(); // create with the default frequency 1.6KHz 29 | //AFMS.begin(1000); // OR with a different frequency, say 1KHz 30 | 31 | // Set the speed to start, from 0 (off) to 255 (max speed) 32 | myMotor->setSpeed(150); 33 | myMotor->run(FORWARD); 34 | // turn on motor 35 | myMotor->run(RELEASE); 36 | } 37 | 38 | void loop() { 39 | uint8_t i; 40 | 41 | Serial.print("tick"); 42 | 43 | myMotor->run(FORWARD); 44 | for (i=0; i<255; i++) { 45 | myMotor->setSpeed(i); 46 | delay(10); 47 | } 48 | for (i=255; i!=0; i--) { 49 | myMotor->setSpeed(i); 50 | delay(10); 51 | } 52 | 53 | Serial.print("tock"); 54 | 55 | myMotor->run(BACKWARD); 56 | for (i=0; i<255; i++) { 57 | myMotor->setSpeed(i); 58 | delay(10); 59 | } 60 | for (i=255; i!=0; i--) { 61 | myMotor->setSpeed(i); 62 | delay(10); 63 | } 64 | 65 | Serial.print("tech"); 66 | myMotor->run(RELEASE); 67 | delay(1000); 68 | } -------------------------------------------------------------------------------- /GcodeCNCDemo2Axis/ams1.ino: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 2 Axis CNC Demo 3 | // dan@marginallyclever.com 2013-08-30 4 | //------------------------------------------------------------------------------ 5 | // Copyright at end of file. 6 | // please see http://www.github.com/MarginallyClever/GcodeCNCDemo for more information. 7 | 8 | #if CONTROLLER == AMS1 9 | 10 | //------------------------------------------------------------------------------ 11 | // INCLUDES 12 | //------------------------------------------------------------------------------ 13 | #include // https://github.com/MarginallyClever/GcodeCNCDemo/tree/master/arduino_libraries/AFMotorDrawbot 14 | 15 | 16 | //------------------------------------------------------------------------------ 17 | // GLOBALS 18 | //------------------------------------------------------------------------------ 19 | // Initialize Adafruit stepper controller 20 | AF_Stepper m1((int)STEPS_PER_TURN, 1); 21 | AF_Stepper m2((int)STEPS_PER_TURN, 2); 22 | 23 | 24 | //------------------------------------------------------------------------------ 25 | // METHODS 26 | //------------------------------------------------------------------------------ 27 | 28 | void m1step(int dir) { 29 | m1.onestep(dir); 30 | } 31 | 32 | void m2step(int dir) { 33 | m2.onestep(dir); 34 | } 35 | 36 | void disable() { 37 | m1.release(); 38 | m2.release(); 39 | } 40 | 41 | 42 | void setup_controller() {} 43 | 44 | 45 | #endif // CONTROLLER == AMS1 46 | /** 47 | * This file is part of GcodeCNCDemo. 48 | * 49 | * GcodeCNCDemo is free software: you can redistribute it and/or modify 50 | * it under the terms of the GNU General Public License as published by 51 | * the Free Software Foundation, either version 3 of the License, or 52 | * (at your option) any later version. 53 | * 54 | * GcodeCNCDemo is distributed in the hope that it will be useful, 55 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 56 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 57 | * GNU General Public License for more details. 58 | * 59 | * You should have received a copy of the GNU General Public License 60 | * along with Foobar. If not, see . 61 | */ 62 | -------------------------------------------------------------------------------- /GcodeCNCDemo2Axis/HG7881.ino: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 2 Axis CNC Demo 3 | // dan@marginallyclever.com 2013-08-30 4 | // modified by lsahidin@yahoo.com added HG7881 stepper controller 5 | //------------------------------------------------------------------------------ 6 | // Copyright at end of file. 7 | // please see http://www.github.com/MarginallyClever/GcodeCNCDemo for more information. 8 | 9 | // Warning. 10 | // * to reduce and avoid overheat on HG7881, use M18 after every G00, G01, G02, G03 on Gcode * \\ 11 | 12 | #if CONTROLLER == HG7881 13 | 14 | //------------------------------------------------------------------------------ 15 | // INCLUDES 16 | //------------------------------------------------------------------------------ 17 | #include 18 | 19 | 20 | //------------------------------------------------------------------------------ 21 | // GLOBALS 22 | //------------------------------------------------------------------------------ 23 | // Initialize HG7881 stepper controller 24 | // HG7881Step motor(Step, pinA_IA, pinA_IB, pinB_IA, pin_B_IB); 25 | HG7881Step m1((int)STEPS_PER_TURN, 9, 5, 10, 6); 26 | HG7881Step m2((int)STEPS_PER_TURN, 0, 6, 5, 7); 27 | 28 | 29 | //------------------------------------------------------------------------------ 30 | // METHODS 31 | //------------------------------------------------------------------------------ 32 | 33 | void m1step(int dir) { 34 | m1.onestep(dir); 35 | } 36 | 37 | void m2step(int dir) { 38 | m2.onestep(dir); 39 | } 40 | 41 | void disable() { 42 | m1.release(); 43 | m2.release(); 44 | } 45 | 46 | 47 | void setup_controller() {} 48 | 49 | 50 | #endif // CONTROLLER == HG7881 51 | /** 52 | * This file is part of GcodeCNCDemo. 53 | * 54 | * GcodeCNCDemo is free software: you can redistribute it and/or modify 55 | * it under the terms of the GNU General Public License as published by 56 | * the Free Software Foundation, either version 3 of the License, or 57 | * (at your option) any later version. 58 | * 59 | * GcodeCNCDemo is distributed in the hope that it will be useful, 60 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 61 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 62 | * GNU General Public License for more details. 63 | * 64 | * You should have received a copy of the GNU General Public License 65 | * along with Foobar. If not, see . 66 | */ 67 | 68 | -------------------------------------------------------------------------------- /arduino_libraries/Adafruit_MotorShield/examples/StackingTest/StackingTest.ino: -------------------------------------------------------------------------------- 1 | /* 2 | This is a test sketch for the Adafruit assembled Motor Shield for Arduino v2 3 | It won't work with v1.x motor shields! Only for the v2's with built in PWM 4 | control 5 | 6 | For use with the Adafruit Motor Shield v2 7 | ----> http://www.adafruit.com/products/1438 8 | */ 9 | 10 | #include 11 | #include 12 | #include "utility/Adafruit_PWMServoDriver.h" 13 | 14 | Adafruit_MotorShield AFMSbot(0x61); // Rightmost jumper closed 15 | Adafruit_MotorShield AFMStop(0x60); // Default address, no jumpers 16 | 17 | // On the top shield, connect two steppers, each with 200 steps 18 | Adafruit_StepperMotor *myStepper2 = AFMStop.getStepper(200, 1); 19 | Adafruit_StepperMotor *myStepper3 = AFMStop.getStepper(200, 2); 20 | 21 | // On the bottom shield connect a stepper to port M3/M4 with 200 steps 22 | Adafruit_StepperMotor *myStepper1 = AFMSbot.getStepper(200, 2); 23 | // And a DC Motor to port M1 24 | Adafruit_DCMotor *myMotor1 = AFMSbot.getMotor(1); 25 | 26 | void setup() { 27 | while (!Serial); 28 | Serial.begin(9600); // set up Serial library at 9600 bps 29 | Serial.println("MMMMotor party!"); 30 | 31 | AFMSbot.begin(); // Start the bottom shield 32 | AFMStop.begin(); // Start the top shield 33 | 34 | // turn on the DC motor 35 | myMotor1->setSpeed(200); 36 | myMotor1->run(RELEASE); 37 | } 38 | 39 | int i; 40 | void loop() { 41 | myMotor1->run(FORWARD); 42 | 43 | for (i=0; i<255; i++) { 44 | myMotor1->setSpeed(i); 45 | myStepper1->onestep(FORWARD, INTERLEAVE); 46 | myStepper2->onestep(BACKWARD, DOUBLE); 47 | myStepper3->onestep(FORWARD, MICROSTEP); 48 | delay(3); 49 | } 50 | 51 | for (i=255; i!=0; i--) { 52 | myMotor1->setSpeed(i); 53 | myStepper1->onestep(BACKWARD, INTERLEAVE); 54 | myStepper2->onestep(FORWARD, DOUBLE); 55 | myStepper3->onestep(BACKWARD, MICROSTEP); 56 | delay(3); 57 | } 58 | 59 | myMotor1->run(BACKWARD); 60 | 61 | for (i=0; i<255; i++) { 62 | myMotor1->setSpeed(i); 63 | myStepper1->onestep(FORWARD, DOUBLE); 64 | myStepper2->onestep(BACKWARD, INTERLEAVE); 65 | myStepper3->onestep(FORWARD, MICROSTEP); 66 | delay(3); 67 | } 68 | 69 | for (i=255; i!=0; i--) { 70 | myMotor1->setSpeed(i); 71 | myStepper1->onestep(BACKWARD, DOUBLE); 72 | myStepper2->onestep(FORWARD, INTERLEAVE); 73 | myStepper3->onestep(BACKWARD, MICROSTEP); 74 | delay(3); 75 | } 76 | } -------------------------------------------------------------------------------- /arduino_libraries/Adafruit_MotorShield/examples/MotorParty/MotorParty.ino: -------------------------------------------------------------------------------- 1 | /* 2 | This is a test sketch for the Adafruit assembled Motor Shield for Arduino v2 3 | It won't work with v1.x motor shields! Only for the v2's with built in PWM 4 | control 5 | 6 | For use with the Adafruit Motor Shield v2 7 | ----> http://www.adafruit.com/products/1438 8 | 9 | This sketch creates a fun motor party on your desk *whiirrr* 10 | Connect a unipolar/bipolar stepper to M3/M4 11 | Connect a DC motor to M1 12 | Connect a hobby servo to SERVO1 13 | */ 14 | 15 | #include 16 | #include 17 | #include "utility/Adafruit_PWMServoDriver.h" 18 | #include 19 | 20 | // Create the motor shield object with the default I2C address 21 | Adafruit_MotorShield AFMS = Adafruit_MotorShield(); 22 | // Or, create it with a different I2C address (say for stacking) 23 | // Adafruit_MotorShield AFMS = Adafruit_MotorShield(0x61); 24 | 25 | // Connect a stepper motor with 200 steps per revolution (1.8 degree) 26 | // to motor port #2 (M3 and M4) 27 | Adafruit_StepperMotor *myStepper = AFMS.getStepper(200, 2); 28 | // And connect a DC motor to port M1 29 | Adafruit_DCMotor *myMotor = AFMS.getMotor(1); 30 | 31 | // We'll also test out the built in Arduino Servo library 32 | Servo servo1; 33 | 34 | 35 | void setup() { 36 | Serial.begin(9600); // set up Serial library at 9600 bps 37 | Serial.println("MMMMotor party!"); 38 | 39 | AFMS.begin(); // create with the default frequency 1.6KHz 40 | //AFMS.begin(1000); // OR with a different frequency, say 1KHz 41 | 42 | // Attach a servo to pin #10 43 | servo1.attach(10); 44 | 45 | // turn on motor M1 46 | myMotor->setSpeed(200); 47 | myMotor->run(RELEASE); 48 | 49 | // setup the stepper 50 | myStepper->setSpeed(10); // 10 rpm 51 | } 52 | 53 | int i; 54 | void loop() { 55 | myMotor->run(FORWARD); 56 | for (i=0; i<255; i++) { 57 | servo1.write(map(i, 0, 255, 0, 180)); 58 | myMotor->setSpeed(i); 59 | myStepper->step(1, FORWARD, INTERLEAVE); 60 | delay(3); 61 | } 62 | 63 | for (i=255; i!=0; i--) { 64 | servo1.write(map(i, 0, 255, 0, 180)); 65 | myMotor->setSpeed(i); 66 | myStepper->step(1, BACKWARD, INTERLEAVE); 67 | delay(3); 68 | } 69 | 70 | myMotor->run(BACKWARD); 71 | for (i=0; i<255; i++) { 72 | servo1.write(map(i, 0, 255, 0, 180)); 73 | myMotor->setSpeed(i); 74 | myStepper->step(1, FORWARD, DOUBLE); 75 | delay(3); 76 | } 77 | 78 | for (i=255; i!=0; i--) { 79 | servo1.write(map(i, 0, 255, 0, 180)); 80 | myMotor->setSpeed(i); 81 | myStepper->step(1, BACKWARD, DOUBLE); 82 | delay(3); 83 | } 84 | } -------------------------------------------------------------------------------- /GcodeCNCDemo2Axis/PassThroughStep.ino: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 2 Axis CNC Demo 3 | // dan@marginallyclever.com 2013-08-30 4 | // modified by lsahidin@yahoo.com added HG7881 stepper controller 5 | // modified by drf5na@gmail.com added a simple pass-through Stepper.h driver 6 | //------------------------------------------------------------------------------ 7 | // Copyright at end of file. 8 | // please see http://www.github.com/MarginallyClever/GcodeCNCDemo for more information. 9 | 10 | // Warning. 11 | // * to reduce and avoid overheat on HG7881, use M18 after every G00, G01, G02, G03 on Gcode * \\ 12 | 13 | #if CONTROLLER == PASS_STEP 14 | 15 | //------------------------------------------------------------------------------ 16 | // INCLUDES 17 | //------------------------------------------------------------------------------ 18 | #include // https://github.com/arduino-libraries/Stepper/blob/master/src/Stepper.h 19 | 20 | 21 | //------------------------------------------------------------------------------ 22 | // GLOBALS 23 | //------------------------------------------------------------------------------ 24 | // Initialize Stepper.h stepper controller 25 | // Stepper.h motor(Step, pinA_IA, pinA_IB, pinB_IA, pin_B_IB); 26 | Stepper m1((int)STEPS_PER_TURN, 6,7,8,9); 27 | Stepper m2((int)STEPS_PER_TURN, 5,4,3,2); 28 | 29 | 30 | //------------------------------------------------------------------------------ 31 | // METHODS 32 | //------------------------------------------------------------------------------ 33 | 34 | void m1step(int dir) { 35 | m1.step(dir); 36 | } 37 | 38 | void m2step(int dir) { 39 | m2.step(dir); 40 | } 41 | 42 | void disable() { 43 | //m1.release(); 44 | //m2.release(); 45 | } 46 | 47 | 48 | void setup_controller() { 49 | ; 50 | m1.setSpeed(100); 51 | m2.setSpeed(100); 52 | } 53 | 54 | 55 | #endif // CONTROLLER == PASS_STEP 56 | /** 57 | * This file is part of GcodeCNCDemo. 58 | * 59 | * GcodeCNCDemo is free software: you can redistribute it and/or modify 60 | * it under the terms of the GNU General Public License as published by 61 | * the Free Software Foundation, either version 3 of the License, or 62 | * (at your option) any later version. 63 | * 64 | * GcodeCNCDemo is distributed in the hope that it will be useful, 65 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 66 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 67 | * GNU General Public License for more details. 68 | * 69 | * You should have received a copy of the GNU General Public License 70 | * along with Foobar. If not, see . 71 | */ 72 | 73 | 74 | -------------------------------------------------------------------------------- /GcodeCNCDemo2Axis/config.h: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_H 2 | #define CONFIG_H 3 | //------------------------------------------------------------------------------ 4 | // 2 Axis CNC Demo 5 | // dan@marginallyclever.com 2013-08-30 6 | //------------------------------------------------------------------------------ 7 | // Copyright at end of file. 8 | // please see http://www.github.com/MarginallyClever/GcodeCNCDemo for more information. 9 | 10 | 11 | //------------------------------------------------------------------------------ 12 | // CONSTANTS 13 | //------------------------------------------------------------------------------ 14 | // supported control boards 15 | #define AMS1 (1) 16 | #define AMS2 (2) 17 | #define HG7881 (3) // HG7881 Stepper Driver 18 | #define PASS_STEP (4) // pass-through 4 wire Stepper.h driver 19 | #define CNCV3 (5) // CNC Shield V3 https://blog.protoneer.co.nz/arduino-cnc-shield/ 20 | 21 | // change this line to select a different control board for your CNC. 22 | #define CONTROLLER CNCV3 23 | 24 | 25 | #define VERSION (1) // firmware version 26 | #define BAUD (57600) // How fast is the Arduino talking? 27 | #define MAX_BUF (64) // What is the longest message Arduino can store? 28 | #define STEPS_PER_TURN (400) // depends on your stepper motor. most are 200. 29 | #define MIN_STEP_DELAY (50.0) 30 | #define MAX_FEEDRATE (1000000.0/MIN_STEP_DELAY) 31 | #define MIN_FEEDRATE (0.01) 32 | //#define INVERT_Y (1) // invert Y axis direction 33 | 34 | // for arc directions 35 | #define ARC_CW (1) 36 | #define ARC_CCW (-1) 37 | // Arcs are split into many line segments. How long are the segments? 38 | #define MM_PER_SEGMENT (10) 39 | 40 | 41 | //------------------------------------------------------------------------------ 42 | // METHODS 43 | //------------------------------------------------------------------------------ 44 | extern void m1step(int dir); 45 | extern void m2step(int dir); 46 | extern void disable(); 47 | extern void setup_controller(); 48 | 49 | 50 | /** 51 | * This file is part of GcodeCNCDemo. 52 | * 53 | * GcodeCNCDemo is free software: you can redistribute it and/or modify 54 | * it under the terms of the GNU General Public License as published by 55 | * the Free Software Foundation, either version 3 of the License, or 56 | * (at your option) any later version. 57 | * 58 | * GcodeCNCDemo is distributed in the hope that it will be useful, 59 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 60 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 61 | * GNU General Public License for more details. 62 | * 63 | * You should have received a copy of the GNU General Public License 64 | * along with Foobar. If not, see . 65 | */ 66 | #endif 67 | -------------------------------------------------------------------------------- /arduino_libraries/HG7881Step/HG7881Step.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * HG7881 Stepper driver for GCodeCNCDemo 3 | 4 | * HG7881Step.h 5 | * 1/8 step for HG7881 6 | * by Luqman Sahidin, 2015 7 | 8 | The sequence of control signals for 4 control wires is as follows: 9 | 10 | Step C0 C1 C2 C3 11 | 1 1 0 1 0 \ 12 | 2 1 1 1 0 | 13 | 3 0 1 1 0 / 14 | 4 0 1 1 1 - 15 | 5 0 1 0 1 \ 16 | 6 1 1 0 1 | 17 | 7 1 0 0 1 / 18 | 8 1 0 1 1 - 19 | 20 | */ 21 | 22 | 23 | #include "Arduino.h" 24 | #include "HG7881Step.h" 25 | 26 | 27 | /* 28 | * constructor for 4-pin version 29 | * Sets which wires should control the motor. 30 | */ 31 | 32 | //--Full Step--// 33 | //int coil_seq[4][4] = {{1,0,1,0},{0,1,1,0},{0,1,0,1},{1,0,0,1}}; 34 | 35 | //--Half Step--// 36 | int coil_seq[8][4] = {{1,0,1,0},{1,1,1,0},{0,1,1,0},{0,1,1,1},{0,1,0,1},{1,1,0,1},{1,0,0,1},{1,0,1,1}}; 37 | 38 | int thisStep; 39 | int currentstep; 40 | 41 | HG7881Step::HG7881Step(int number_of_steps, int motor_pin_1, int motor_pin_2, int motor_pin_3, int motor_pin_4) 42 | { 43 | currentstep = 0; 44 | 45 | // Arduino pins for the motor control connection: 46 | this->pinA_IA = motor_pin_1; 47 | this->pinA_IB = motor_pin_2; 48 | this->pinB_IA = motor_pin_3; 49 | this->pinB_IB = motor_pin_4; 50 | 51 | // setup the pins on the microcontroller: 52 | pinMode(this->pinA_IA, OUTPUT); 53 | pinMode(this->pinA_IB, OUTPUT); 54 | pinMode(this->pinB_IA, OUTPUT); 55 | pinMode(this->pinB_IB, OUTPUT); 56 | 57 | } 58 | 59 | /* 60 | * release all coils 61 | * HG7881 needs this to not drive the motor unnecessarily 62 | * to avoid produce more heat on IC's 63 | */ 64 | void HG7881Step::release(){ 65 | digitalWrite(this->pinA_IA, LOW); 66 | digitalWrite(this->pinA_IB, LOW); 67 | digitalWrite(this->pinB_IA, LOW); 68 | digitalWrite(this->pinB_IB, LOW); 69 | } 70 | 71 | /* 72 | * Moves the motor forward or backwards. 73 | * If the number is negative, 74 | the motor moves in the reverse direction. 75 | */ 76 | void HG7881Step::onestep(int dir) 77 | { 78 | if((currentstep/(MICROSTEPS/2)) % 2) { // we're at an odd step, weird 79 | if(dir == FORWARD) currentstep += MICROSTEPS/2; 80 | else currentstep -= MICROSTEPS/2; 81 | } else { // go to the next even step 82 | if(dir == FORWARD) currentstep += MICROSTEPS; 83 | else currentstep -= MICROSTEPS; 84 | } 85 | 86 | currentstep += MICROSTEPS*4; 87 | currentstep %= MICROSTEPS*4; 88 | 89 | thisStep = currentstep/(MICROSTEPS/2); 90 | 91 | /* Energize the coil by sequence */ 92 | digitalWrite(pinA_IA, coil_seq[thisStep][0]); 93 | digitalWrite(pinA_IB, coil_seq[thisStep][1]); 94 | digitalWrite(pinB_IA, coil_seq[thisStep][2]); 95 | digitalWrite(pinB_IB, coil_seq[thisStep][3]); 96 | 97 | } 98 | -------------------------------------------------------------------------------- /GcodeCNCDemo2Axis/RAMPS.ino: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 2 Axis CNC Demo 3 | // dan@marginallyclever.com 2015-12-23 4 | //------------------------------------------------------------------------------ 5 | // Copyright at end of file. 6 | // please see http://www.github.com/MarginallyClever/GcodeCNCDemo for more information. 7 | 8 | #if CONTROLLER == RAMPS 9 | 10 | //------------------------------------------------------------------------------ 11 | // INCLUDES 12 | //------------------------------------------------------------------------------ 13 | 14 | 15 | //------------------------------------------------------------------------------ 16 | // CONSTANTS 17 | //------------------------------------------------------------------------------ 18 | #define M1_STEP 54 19 | #define M1_DIR 55 20 | #define M1_ENA 38 21 | 22 | #define M2_STEP 60 23 | #define M2_DIR 61 24 | #define M2_ENA 56 25 | 26 | // limit switches 27 | #define SWITCH1 3 28 | #define SWITCH2 14 29 | 30 | //------------------------------------------------------------------------------ 31 | // GLOBALS 32 | //------------------------------------------------------------------------------ 33 | 34 | //------------------------------------------------------------------------------ 35 | // METHODS 36 | //------------------------------------------------------------------------------ 37 | 38 | void m1step(int dir) { 39 | digitalWrite(M1_ENA,HIGH); 40 | digitalWrite(M1_DIR,dir==1?HIGH:LOW); 41 | digitalWrite(M1_STEP,HIGH); 42 | digitalWrite(M1_STEP,LOW); 43 | } 44 | 45 | void m2step(int dir) { 46 | digitalWrite(M2_ENA,HIGH); 47 | digitalWrite(M2_DIR,dir==1?HIGH:LOW); 48 | digitalWrite(M2_STEP,HIGH); 49 | digitalWrite(M2_STEP,LOW); 50 | } 51 | 52 | void disable() { 53 | digitalWrite(M1_ENA,LOW); 54 | digitalWrite(M2_ENA,LOW); 55 | } 56 | 57 | 58 | void setup_controller() { 59 | pinMode(M1_ENA,OUTPUT); 60 | pinMode(M2_ENA,OUTPUT); 61 | pinMode(M1_STEP,OUTPUT); 62 | pinMode(M2_STEP,OUTPUT); 63 | pinMode(M1_DIR,OUTPUT); 64 | pinMode(M2_DIR,OUTPUT); 65 | } 66 | 67 | 68 | #endif // CONTROLLER == RAMPS 69 | /** 70 | * This file is part of GcodeCNCDemo. 71 | * 72 | * GcodeCNCDemo is free software: you can redistribute it and/or modify 73 | * it under the terms of the GNU General Public License as published by 74 | * the Free Software Foundation, either version 3 of the License, or 75 | * (at your option) any later version. 76 | * 77 | * GcodeCNCDemo is distributed in the hope that it will be useful, 78 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 79 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 80 | * GNU General Public License for more details. 81 | * 82 | * You should have received a copy of the GNU General Public License 83 | * along with Foobar. If not, see . 84 | */ 85 | -------------------------------------------------------------------------------- /GcodeCNCDemo2Axis/CNCV3.ino: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 2 Axis CNC Demo 3 | // dan@marginallyclever.com 2015-12-23 4 | //------------------------------------------------------------------------------ 5 | // Copyright at end of file. 6 | // please see http://www.github.com/MarginallyClever/GcodeCNCDemo for more information. 7 | 8 | #if CONTROLLER == CNCV3 9 | 10 | //------------------------------------------------------------------------------ 11 | // INCLUDES 12 | //------------------------------------------------------------------------------ 13 | 14 | 15 | //------------------------------------------------------------------------------ 16 | // CONSTANTS 17 | //------------------------------------------------------------------------------ 18 | #define M1_STEP 2 19 | #define M1_DIR 5 20 | #define M1_ENA 8 21 | 22 | #define M2_STEP 3 23 | #define M2_DIR 6 24 | #define M2_ENA 8 25 | 26 | // limit switches 27 | #define SWITCH1 9 28 | #define SWITCH2 10 29 | 30 | //------------------------------------------------------------------------------ 31 | // GLOBALS 32 | //------------------------------------------------------------------------------ 33 | 34 | //------------------------------------------------------------------------------ 35 | // METHODS 36 | //------------------------------------------------------------------------------ 37 | 38 | void m1step(int dir) { 39 | digitalWrite(M1_ENA,LOW); 40 | digitalWrite(M1_DIR,dir==1? HIGH:LOW); 41 | digitalWrite(M1_STEP,HIGH); 42 | digitalWrite(M1_STEP,LOW); 43 | } 44 | 45 | void m2step(int dir) { 46 | digitalWrite(M2_ENA,LOW); 47 | digitalWrite(M2_DIR,dir==1?HIGH:LOW); 48 | digitalWrite(M2_STEP,HIGH); 49 | digitalWrite(M2_STEP,LOW); 50 | } 51 | 52 | void disable() { 53 | digitalWrite(M1_ENA,HIGH); 54 | digitalWrite(M2_ENA,HIGH); 55 | } 56 | 57 | 58 | void setup_controller() { 59 | pinMode(M1_ENA,OUTPUT); 60 | pinMode(M2_ENA,OUTPUT); 61 | pinMode(M1_STEP,OUTPUT); 62 | pinMode(M2_STEP,OUTPUT); 63 | pinMode(M1_DIR,OUTPUT); 64 | pinMode(M2_DIR,OUTPUT); 65 | } 66 | 67 | 68 | #endif // CONTROLLER == CNCV3 69 | /** 70 | * This file is part of GcodeCNCDemo. 71 | * 72 | * GcodeCNCDemo is free software: you can redistribute it and/or modify 73 | * it under the terms of the GNU General Public License as published by 74 | * the Free Software Foundation, either version 3 of the License, or 75 | * (at your option) any later version. 76 | * 77 | * GcodeCNCDemo is distributed in the hope that it will be useful, 78 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 79 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 80 | * GNU General Public License for more details. 81 | * 82 | * You should have received a copy of the GNU General Public License 83 | * along with Foobar. If not, see . 84 | */ 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /GcodeCNCDemo2Axis/ams2.ino: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 2 Axis CNC Demo 3 | // dan@marginallyclever.com 2013-08-30 4 | //------------------------------------------------------------------------------ 5 | // Copyright at end of file. 6 | // please see http://www.github.com/MarginallyClever/GcodeCNCDemo for more information. 7 | 8 | #include "config.h" 9 | 10 | #if CONTROLLER == AMS2 11 | 12 | //------------------------------------------------------------------------------ 13 | // INCLUDES 14 | //------------------------------------------------------------------------------ 15 | 16 | #include 17 | #include 18 | #include "utility/Adafruit_PWMServoDriver.h" 19 | 20 | 21 | #if CONTROLLER == AMS2 22 | 23 | // Make sure you set the right address. If you aren't sure, 24 | // use http://playground.arduino.cc/Main/I2cScanner to find it. 25 | //#define AFMS2_ADDRESS (0x60) 26 | 27 | #ifndef AFMS2_ADDRESS 28 | #error AFMS2_ADDRESS must be defined! 29 | #endif 30 | #endif 31 | 32 | //------------------------------------------------------------------------------ 33 | // GLOBALS 34 | //------------------------------------------------------------------------------ 35 | 36 | // Create the motor shield object with the default I2C address 37 | Adafruit_MotorShield AFMS = Adafruit_MotorShield(AFMS2_ADDRESS); 38 | Adafruit_StepperMotor *m1 = AFMS.getStepper(STEPS_PER_TURN, 1); // to motor port #1 (M1 and M2) 39 | Adafruit_StepperMotor *m2 = AFMS.getStepper(STEPS_PER_TURN, 2); // to motor port #2 (M3 and M4) 40 | 41 | 42 | //------------------------------------------------------------------------------ 43 | // METHODS 44 | //------------------------------------------------------------------------------ 45 | 46 | void m1step(int dir) { 47 | m1->onestep(dir>0?FORWARD:BACKWARD,SINGLE); 48 | } 49 | 50 | void m2step(int dir) { 51 | m2->onestep(dir>0?FORWARD:BACKWARD,SINGLE); 52 | } 53 | 54 | void disable() { 55 | m1->release(); 56 | m2->release(); 57 | } 58 | 59 | 60 | void setup_controller() { 61 | AFMS.begin(); // create with the default frequency 1.6KHz 62 | } 63 | 64 | 65 | #endif // CONTROLLER == AMS2 66 | 67 | /** 68 | * This file is part of GcodeCNCDemo. 69 | * 70 | * GcodeCNCDemo is free software: you can redistribute it and/or modify 71 | * it under the terms of the GNU General Public License as published by 72 | * the Free Software Foundation, either version 3 of the License, or 73 | * (at your option) any later version. 74 | * 75 | * GcodeCNCDemo is distributed in the hope that it will be useful, 76 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 77 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 78 | * GNU General Public License for more details. 79 | * 80 | * You should have received a copy of the GNU General Public License 81 | * along with Foobar. If not, see . 82 | */ 83 | -------------------------------------------------------------------------------- /arduino_libraries/Adafruit_MotorShield/examples/Accel_MultiStepper/Accel_MultiStepper.ino: -------------------------------------------------------------------------------- 1 | // Shows how to run three Steppers at once with varying speeds 2 | // 3 | // Requires the Adafruit_Motorshield v2 library 4 | // https://github.com/adafruit/Adafruit_Motor_Shield_V2_Library 5 | // And AccelStepper with AFMotor support 6 | // https://github.com/adafruit/AccelStepper 7 | 8 | // This tutorial is for Adafruit Motorshield v2 only! 9 | // Will not work with v1 shields 10 | 11 | #include 12 | #include 13 | #include 14 | #include "utility/Adafruit_PWMServoDriver.h" 15 | 16 | Adafruit_MotorShield AFMSbot(0x61); // Rightmost jumper closed 17 | Adafruit_MotorShield AFMStop(0x60); // Default address, no jumpers 18 | 19 | // Connect two steppers with 200 steps per revolution (1.8 degree) 20 | // to the top shield 21 | Adafruit_StepperMotor *myStepper1 = AFMStop.getStepper(200, 1); 22 | Adafruit_StepperMotor *myStepper2 = AFMStop.getStepper(200, 2); 23 | 24 | // Connect one stepper with 200 steps per revolution (1.8 degree) 25 | // to the bottom shield 26 | Adafruit_StepperMotor *myStepper3 = AFMSbot.getStepper(200, 2); 27 | 28 | // you can change these to DOUBLE or INTERLEAVE or MICROSTEP! 29 | // wrappers for the first motor! 30 | void forwardstep1() { 31 | myStepper1->onestep(FORWARD, SINGLE); 32 | } 33 | void backwardstep1() { 34 | myStepper1->onestep(BACKWARD, SINGLE); 35 | } 36 | // wrappers for the second motor! 37 | void forwardstep2() { 38 | myStepper2->onestep(FORWARD, DOUBLE); 39 | } 40 | void backwardstep2() { 41 | myStepper2->onestep(BACKWARD, DOUBLE); 42 | } 43 | // wrappers for the third motor! 44 | void forwardstep3() { 45 | myStepper3->onestep(FORWARD, INTERLEAVE); 46 | } 47 | void backwardstep3() { 48 | myStepper3->onestep(BACKWARD, INTERLEAVE); 49 | } 50 | 51 | // Now we'll wrap the 3 steppers in an AccelStepper object 52 | AccelStepper stepper1(forwardstep1, backwardstep1); 53 | AccelStepper stepper2(forwardstep2, backwardstep2); 54 | AccelStepper stepper3(forwardstep3, backwardstep3); 55 | 56 | void setup() 57 | { 58 | AFMSbot.begin(); // Start the bottom shield 59 | AFMStop.begin(); // Start the top shield 60 | 61 | stepper1.setMaxSpeed(100.0); 62 | stepper1.setAcceleration(100.0); 63 | stepper1.moveTo(24); 64 | 65 | stepper2.setMaxSpeed(200.0); 66 | stepper2.setAcceleration(100.0); 67 | stepper2.moveTo(50000); 68 | 69 | stepper3.setMaxSpeed(300.0); 70 | stepper3.setAcceleration(100.0); 71 | stepper3.moveTo(1000000); 72 | } 73 | 74 | void loop() 75 | { 76 | // Change direction at the limits 77 | if (stepper1.distanceToGo() == 0) 78 | stepper1.moveTo(-stepper1.currentPosition()); 79 | 80 | if (stepper2.distanceToGo() == 0) 81 | stepper2.moveTo(-stepper2.currentPosition()); 82 | 83 | if (stepper3.distanceToGo() == 0) 84 | stepper3.moveTo(-stepper3.currentPosition()); 85 | 86 | stepper1.run(); 87 | stepper2.run(); 88 | stepper3.run(); 89 | } 90 | 91 | -------------------------------------------------------------------------------- /arduino_libraries/Adafruit_MotorShield/Adafruit_MotorShield.h: -------------------------------------------------------------------------------- 1 | /****************************************************************** 2 | This is the library for the Adafruit Motor Shield V2 for Arduino. 3 | It supports DC motors & Stepper motors with microstepping as well 4 | as stacking-support. It is *not* compatible with the V1 library! 5 | 6 | It will only work with https://www.adafruit.com/products/1483 7 | 8 | Adafruit invests time and resources providing this open 9 | source code, please support Adafruit and open-source hardware 10 | by purchasing products from Adafruit! 11 | 12 | Written by Limor Fried/Ladyada for Adafruit Industries. 13 | BSD license, check license.txt for more information. 14 | All text above must be included in any redistribution. 15 | ******************************************************************/ 16 | 17 | #ifndef _Adafruit_MotorShield_h_ 18 | #define _Adafruit_MotorShield_h_ 19 | 20 | #include 21 | #include 22 | #include "utility/Adafruit_PWMServoDriver.h" 23 | 24 | //#define MOTORDEBUG 25 | 26 | #define MICROSTEPS 16 // 8 or 16 27 | 28 | #define MOTOR1_A 2 29 | #define MOTOR1_B 3 30 | #define MOTOR2_A 1 31 | #define MOTOR2_B 4 32 | #define MOTOR4_A 0 33 | #define MOTOR4_B 6 34 | #define MOTOR3_A 5 35 | #define MOTOR3_B 7 36 | 37 | #define FORWARD 1 38 | #define BACKWARD 2 39 | #define BRAKE 3 40 | #define RELEASE 4 41 | 42 | #define SINGLE 1 43 | #define DOUBLE 2 44 | #define INTERLEAVE 3 45 | #define MICROSTEP 4 46 | 47 | class Adafruit_MotorShield; 48 | 49 | class Adafruit_DCMotor 50 | { 51 | public: 52 | Adafruit_DCMotor(void); 53 | friend class Adafruit_MotorShield; 54 | void run(uint8_t); 55 | void setSpeed(uint8_t); 56 | 57 | private: 58 | uint8_t PWMpin, IN1pin, IN2pin; 59 | Adafruit_MotorShield *MC; 60 | uint8_t motornum; 61 | }; 62 | 63 | class Adafruit_StepperMotor { 64 | public: 65 | Adafruit_StepperMotor(void); 66 | friend class Adafruit_MotorShield; 67 | 68 | void step(uint16_t steps, uint8_t dir, uint8_t style = SINGLE); 69 | void setSpeed(uint16_t); 70 | uint8_t onestep(uint8_t dir, uint8_t style); 71 | void release(void); 72 | uint32_t usperstep, steppingcounter; 73 | 74 | private: 75 | uint8_t PWMApin, AIN1pin, AIN2pin; 76 | uint8_t PWMBpin, BIN1pin, BIN2pin; 77 | uint16_t revsteps; // # steps per revolution 78 | uint8_t currentstep; 79 | Adafruit_MotorShield *MC; 80 | uint8_t steppernum; 81 | }; 82 | 83 | class Adafruit_MotorShield 84 | { 85 | public: 86 | Adafruit_MotorShield(uint8_t addr = 0x60); 87 | friend class Adafruit_DCMotor; 88 | void begin(uint16_t freq = 1600); 89 | 90 | void setPWM(uint8_t pin, uint16_t val); 91 | void setPin(uint8_t pin, boolean val); 92 | Adafruit_DCMotor *getMotor(uint8_t n); 93 | Adafruit_StepperMotor *getStepper(uint16_t steps, uint8_t n); 94 | private: 95 | uint8_t _addr; 96 | uint16_t _freq; 97 | Adafruit_DCMotor dcmotors[4]; 98 | Adafruit_StepperMotor steppers[2]; 99 | Adafruit_PWMServoDriver _pwm; 100 | }; 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /arduino_libraries/Adafruit_MotorShield/utility/Adafruit_PWMServoDriver.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | This is a library for our Adafruit 16-channel PWM & Servo driver 3 | 4 | Pick one up today in the adafruit shop! 5 | ------> http://www.adafruit.com/products/815 6 | 7 | These displays use I2C to communicate, 2 pins are required to 8 | interface. For Arduino UNOs, thats SCL -> Analog 5, SDA -> Analog 4 9 | 10 | Adafruit invests time and resources providing this open source code, 11 | please support Adafruit and open-source hardware by purchasing 12 | products from Adafruit! 13 | 14 | Written by Limor Fried/Ladyada for Adafruit Industries. 15 | BSD license, all text above must be included in any redistribution 16 | ****************************************************/ 17 | 18 | #include 19 | #include 20 | #ifdef __AVR__ 21 | #define WIRE Wire 22 | #else // Arduino Due 23 | #define WIRE Wire1 24 | #endif 25 | 26 | Adafruit_PWMServoDriver::Adafruit_PWMServoDriver(uint8_t addr) { 27 | _i2caddr = addr; 28 | } 29 | 30 | void Adafruit_PWMServoDriver::begin(void) { 31 | WIRE.begin(); 32 | reset(); 33 | } 34 | 35 | 36 | void Adafruit_PWMServoDriver::reset(void) { 37 | write8(PCA9685_MODE1, 0x0); 38 | } 39 | 40 | void Adafruit_PWMServoDriver::setPWMFreq(float freq) { 41 | //Serial.print("Attempting to set freq "); 42 | //Serial.println(freq); 43 | 44 | float prescaleval = 25000000; 45 | prescaleval /= 4096; 46 | prescaleval /= freq; 47 | prescaleval -= 1; 48 | Serial.print("Estimated pre-scale: "); Serial.println(prescaleval); 49 | uint8_t prescale = floor(prescaleval + 0.5); 50 | Serial.print("Final pre-scale: "); Serial.println(prescale); 51 | 52 | uint8_t oldmode = read8(PCA9685_MODE1); 53 | uint8_t newmode = (oldmode&0x7F) | 0x10; // sleep 54 | write8(PCA9685_MODE1, newmode); // go to sleep 55 | write8(PCA9685_PRESCALE, prescale); // set the prescaler 56 | write8(PCA9685_MODE1, oldmode); 57 | delay(5); 58 | write8(PCA9685_MODE1, oldmode | 0xa1); // This sets the MODE1 register to turn on auto increment. 59 | // This is why the beginTransmission below was not working. 60 | // Serial.print("Mode now 0x"); Serial.println(read8(PCA9685_MODE1), HEX); 61 | } 62 | 63 | void Adafruit_PWMServoDriver::setPWM(uint8_t num, uint16_t on, uint16_t off) { 64 | //Serial.print("Setting PWM "); Serial.print(num); Serial.print(": "); Serial.print(on); Serial.print("->"); Serial.println(off); 65 | 66 | WIRE.beginTransmission(_i2caddr); 67 | #if ARDUINO >= 100 68 | WIRE.write(LED0_ON_L+4*num); 69 | WIRE.write(on); 70 | WIRE.write(on>>8); 71 | WIRE.write(off); 72 | WIRE.write(off>>8); 73 | #else 74 | WIRE.send(LED0_ON_L+4*num); 75 | WIRE.send((uint8_t)on); 76 | WIRE.send((uint8_t)(on>>8)); 77 | WIRE.send((uint8_t)off); 78 | WIRE.send((uint8_t)(off>>8)); 79 | #endif 80 | WIRE.endTransmission(); 81 | } 82 | 83 | uint8_t Adafruit_PWMServoDriver::read8(uint8_t addr) { 84 | WIRE.beginTransmission(_i2caddr); 85 | #if ARDUINO >= 100 86 | WIRE.write(addr); 87 | #else 88 | WIRE.send(addr); 89 | #endif 90 | WIRE.endTransmission(); 91 | 92 | WIRE.requestFrom((uint8_t)_i2caddr, (uint8_t)1); 93 | #if ARDUINO >= 100 94 | return WIRE.read(); 95 | #else 96 | return WIRE.receive(); 97 | #endif 98 | } 99 | 100 | void Adafruit_PWMServoDriver::write8(uint8_t addr, uint8_t d) { 101 | WIRE.beginTransmission(_i2caddr); 102 | #if ARDUINO >= 100 103 | WIRE.write(addr); 104 | WIRE.write(d); 105 | #else 106 | WIRE.send(addr); 107 | WIRE.send(d); 108 | #endif 109 | WIRE.endTransmission(); 110 | } 111 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac crap 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | -------------------------------------------------------------------------------- /arduino_libraries/AFMotorDrawbot/AFMotorDrawbot.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // Adafruit Motor shield library, modified for Drawbot 3 | // copyright Dan Royer, 2012 4 | // this code is public domain, enjoy! 5 | //------------------------------------------------------------------------------ 6 | #if (ARDUINO >= 100) 7 | #include "Arduino.h" 8 | #else 9 | #include 10 | #include "WProgram.h" 11 | #endif 12 | #include "AFMotorDrawbot.h" 13 | 14 | 15 | 16 | //------------------------------------------------------------------------------ 17 | 18 | 19 | 20 | static uint8_t latch_state; 21 | static AFMotorController MC; 22 | 23 | 24 | 25 | //------------------------------------------------------------------------------ 26 | 27 | 28 | 29 | AFMotorController::AFMotorController() {} 30 | 31 | 32 | void AFMotorController::enable() { 33 | // setup the latch 34 | /* 35 | LATCH_DDR |= _BV(LATCH); 36 | ENABLE_DDR |= _BV(ENABLE); 37 | CLK_DDR |= _BV(CLK); 38 | SER_DDR |= _BV(SER); 39 | */ 40 | pinMode(MOTORLATCH, OUTPUT); 41 | pinMode(MOTORENABLE, OUTPUT); 42 | pinMode(MOTORDATA, OUTPUT); 43 | pinMode(MOTORCLK, OUTPUT); 44 | 45 | latch_state = 0; 46 | 47 | latch_tx(); // "reset" 48 | 49 | //ENABLE_PORT &= ~_BV(ENABLE); // enable the chip outputs! 50 | digitalWrite(MOTORENABLE, LOW); 51 | } 52 | 53 | 54 | void AFMotorController::latch_tx() { 55 | uint8_t i; 56 | 57 | //LATCH_PORT &= ~_BV(LATCH); 58 | digitalWrite(MOTORLATCH, LOW); 59 | 60 | //SER_PORT &= ~_BV(SER); 61 | digitalWrite(MOTORDATA, LOW); 62 | 63 | for (i=0; i<8; i++) { 64 | //CLK_PORT &= ~_BV(CLK); 65 | digitalWrite(MOTORCLK, LOW); 66 | 67 | if (latch_state & _BV(7-i)) { 68 | //SER_PORT |= _BV(SER); 69 | digitalWrite(MOTORDATA, HIGH); 70 | } else { 71 | //SER_PORT &= ~_BV(SER); 72 | digitalWrite(MOTORDATA, LOW); 73 | } 74 | //CLK_PORT |= _BV(CLK); 75 | digitalWrite(MOTORCLK, HIGH); 76 | } 77 | //LATCH_PORT |= _BV(LATCH); 78 | digitalWrite(MOTORLATCH, HIGH); 79 | } 80 | 81 | 82 | 83 | //------------------------------------------------------------------------------ 84 | // STEPPERS 85 | //------------------------------------------------------------------------------ 86 | 87 | 88 | 89 | AF_Stepper::AF_Stepper(uint16_t steps, uint8_t num) { 90 | MC.enable(); 91 | 92 | revsteps = steps; 93 | steppernum = num; 94 | currentstep = 0; 95 | 96 | if (steppernum == 1) { 97 | latch_state &= ~_BV(MOTOR1_A) & ~_BV(MOTOR1_B) & 98 | ~_BV(MOTOR2_A) & ~_BV(MOTOR2_B); // all motor pins to 0 99 | MC.latch_tx(); 100 | 101 | // enable both H bridges 102 | pinMode(11, OUTPUT); 103 | pinMode(3, OUTPUT); 104 | digitalWrite(11, HIGH); 105 | digitalWrite(3, HIGH); 106 | 107 | a = _BV(MOTOR1_A); 108 | b = _BV(MOTOR2_A); 109 | c = _BV(MOTOR1_B); 110 | d = _BV(MOTOR2_B); 111 | } else if (steppernum == 2) { 112 | latch_state &= ~_BV(MOTOR3_A) & ~_BV(MOTOR3_B) & 113 | ~_BV(MOTOR4_A) & ~_BV(MOTOR4_B); // all motor pins to 0 114 | MC.latch_tx(); 115 | 116 | // enable both H bridges 117 | pinMode(5, OUTPUT); 118 | pinMode(6, OUTPUT); 119 | digitalWrite(5, HIGH); 120 | digitalWrite(6, HIGH); 121 | 122 | a = _BV(MOTOR3_A); 123 | b = _BV(MOTOR4_A); 124 | c = _BV(MOTOR3_B); 125 | d = _BV(MOTOR4_B); 126 | } 127 | } 128 | 129 | 130 | void AF_Stepper::setSpeed(uint16_t rpm) { 131 | usperstep = 60000000 / ((uint32_t)revsteps * (uint32_t)rpm); 132 | steppingcounter = 0; 133 | } 134 | 135 | 136 | void AF_Stepper::release() { 137 | // release all 138 | latch_state &= ~a & ~b & ~c & ~d; // all motor pins to 0 139 | MC.latch_tx(); 140 | } 141 | 142 | 143 | void AF_Stepper::step(uint16_t steps, uint8_t dir) { 144 | uint32_t uspers = usperstep; 145 | uint8_t ret = 0; 146 | 147 | while (steps--) { 148 | ret = onestep(dir); 149 | //* 150 | delay(uspers/1000); // in ms 151 | steppingcounter += (uspers % 1000); 152 | if (steppingcounter >= 1000) { 153 | delay(1); 154 | steppingcounter -= 1000; 155 | } 156 | //*/ delayMicroseconds(uspers); 157 | } 158 | } 159 | 160 | 161 | uint8_t AF_Stepper::onestep(uint8_t dir) { 162 | if((currentstep/(MICROSTEPS/2)) % 2) { // we're at an odd step, weird 163 | if(dir == FORWARD) currentstep += MICROSTEPS/2; 164 | else currentstep -= MICROSTEPS/2; 165 | } else { // go to the next even step 166 | if(dir == FORWARD) currentstep += MICROSTEPS; 167 | else currentstep -= MICROSTEPS; 168 | } 169 | 170 | currentstep += MICROSTEPS*4; 171 | currentstep %= MICROSTEPS*4; 172 | 173 | #ifdef MOTORDEBUG 174 | Serial.print("current step: "); Serial.println(currentstep, DEC); 175 | #endif 176 | 177 | // preprare to release all coils 178 | latch_state &= ~a & ~b & ~c & ~d; // all motor pins to 0 179 | 180 | // No wait! Keep some energized. 181 | switch (currentstep/(MICROSTEPS/2)) { 182 | case 0: latch_state |= a; break; // energize coil 1 only 183 | case 1: latch_state |= a | b; break; // energize coil 1+2 184 | case 2: latch_state |= b; break; // energize coil 2 only 185 | case 3: latch_state |= b | c; break; // energize coil 2+3 186 | case 4: latch_state |= c; break; // energize coil 3 only 187 | case 5: latch_state |= c | d; break; // energize coil 3+4 188 | case 6: latch_state |= d; break; // energize coil 4 only 189 | case 7: latch_state |= d | a; break; // energize coil 1+4 190 | } 191 | 192 | // change the energized state now 193 | MC.latch_tx(); 194 | 195 | return currentstep; 196 | } 197 | 198 | -------------------------------------------------------------------------------- /GcodeCNCDemo2Axis/GcodeCNCDemo2Axis.ino: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 2 Axis CNC Demo 3 | // dan@marginallyclever.com 2013-08-30 4 | //------------------------------------------------------------------------------ 5 | // Copyright at end of file. 6 | // please see http://www.github.com/MarginallyClever/GcodeCNCDemo for more information. 7 | 8 | #include "config.h" 9 | 10 | //------------------------------------------------------------------------------ 11 | // GLOBALS 12 | //------------------------------------------------------------------------------ 13 | 14 | char serialBuffer[MAX_BUF]; // where we store the message until we get a newline 15 | int sofar; // how much is in the serialBuffer 16 | float px, py; // location 17 | 18 | // speeds 19 | float fr = 0; // human version 20 | long step_delay; // machine version 21 | 22 | // settings 23 | char mode_abs=1; // absolute mode? 24 | 25 | 26 | //------------------------------------------------------------------------------ 27 | // METHODS 28 | //------------------------------------------------------------------------------ 29 | 30 | 31 | /** 32 | * delay for the appropriate number of microseconds 33 | * @input ms how many milliseconds to wait 34 | */ 35 | void pause(long ms) { 36 | delay(ms/1000); 37 | delayMicroseconds(ms%1000); // delayMicroseconds doesn't work for values > ~16k. 38 | } 39 | 40 | 41 | /** 42 | * Set the feedrate (speed motors will move) 43 | * @input nfr the new speed in steps/second 44 | */ 45 | void feedrate(float nfr) { 46 | if(fr==nfr) return; // same as last time? quit now. 47 | 48 | if(nfr>MAX_FEEDRATE || nfr0?1:-1; 85 | #ifdef INVERT_Y 86 | int diry = dy>0?-1:1; // because the motors are mounted in opposite directions 87 | #else 88 | int diry = dy>0?1:-1; 89 | #endif 90 | dx = abs(dx); 91 | dy = abs(dy); 92 | 93 | if(dx>dy) { 94 | over = dx/2; 95 | for(i=0; i=dx) { 99 | over -= dx; 100 | m2step(diry); 101 | } 102 | pause(step_delay); 103 | } 104 | } else { 105 | over = dy/2; 106 | for(i=0; i= dy) { 110 | over -= dy; 111 | m1step(dirx); 112 | } 113 | pause(step_delay); 114 | } 115 | } 116 | 117 | px = newx; 118 | py = newy; 119 | } 120 | 121 | 122 | // returns angle of dy/dx as a value from 0...2PI 123 | float atan3(float dy,float dx) { 124 | float a = atan2(dy,dx); 125 | if(a<0) a = (PI*2.0)+a; 126 | return a; 127 | } 128 | 129 | 130 | // This method assumes the limits have already been checked. 131 | // This method assumes the start and end radius match. 132 | // This method assumes arcs are not >180 degrees (PI radians) 133 | // cx/cy - center of circle 134 | // x/y - end position 135 | // dir - ARC_CW or ARC_CCW to control direction of arc 136 | void arc(float cx,float cy,float x,float y,float dir) { 137 | // get radius 138 | float dx = px - cx; 139 | float dy = py - cy; 140 | float radius=sqrt(dx*dx+dy*dy); 141 | 142 | // find angle of arc (sweep) 143 | float angle1=atan3(dy,dx); 144 | float angle2=atan3(y-cy,x-cx); 145 | float theta=angle2-angle1; 146 | 147 | if(dir>0 && theta<0) angle2+=2*PI; 148 | else if(dir<0 && theta>0) angle1+=2*PI; 149 | 150 | theta=angle2-angle1; 151 | 152 | // get length of arc 153 | // float circ=PI*2.0*radius; 154 | // float len=theta*circ/(PI*2.0); 155 | // simplifies to 156 | float len = abs(theta) * radius; 157 | 158 | int i, segments = ceil( len * MM_PER_SEGMENT ); 159 | 160 | float nx, ny, angle3, scale; 161 | 162 | for(i=0;i 1 && (*ptr) && (long)ptr < (long)serialBuffer+sofar) { // walk to the end 186 | if(*ptr==code) { // if you find code on your walk, 187 | return atof(ptr+1); // convert the digits that follow into a float and return it 188 | } 189 | ptr=strchr(ptr,' ')+1; // take a step from here to the letter after the next space 190 | } 191 | return val; // end reached, nothing found, return default val. 192 | } 193 | 194 | 195 | /** 196 | * write a string followed by a float to the serial line. Convenient for debugging. 197 | * @input code the string. 198 | * @input val the float. 199 | */ 200 | void output(const char *code,float val) { 201 | Serial.print(code); 202 | Serial.println(val); 203 | } 204 | 205 | 206 | /** 207 | * print the current position, feedrate, and absolute mode. 208 | */ 209 | void where() { 210 | output("X",px); 211 | output("Y",py); 212 | output("F",fr); 213 | Serial.println(mode_abs?"ABS":"REL"); 214 | } 215 | 216 | 217 | /** 218 | * display helpful information 219 | */ 220 | void help() { 221 | Serial.print(F("GcodeCNCDemo2AxisV1 ")); 222 | Serial.println(VERSION); 223 | Serial.println(F("Commands:")); 224 | Serial.println(F("G00 [X(steps)] [Y(steps)] [F(feedrate)]; - line")); 225 | Serial.println(F("G01 [X(steps)] [Y(steps)] [F(feedrate)]; - line")); 226 | Serial.println(F("G02 [X(steps)] [Y(steps)] [I(steps)] [J(steps)] [F(feedrate)]; - clockwise arc")); 227 | Serial.println(F("G03 [X(steps)] [Y(steps)] [I(steps)] [J(steps)] [F(feedrate)]; - counter-clockwise arc")); 228 | Serial.println(F("G04 P[seconds]; - delay")); 229 | Serial.println(F("G90; - absolute mode")); 230 | Serial.println(F("G91; - relative mode")); 231 | Serial.println(F("G92 [X(steps)] [Y(steps)]; - change logical position")); 232 | Serial.println(F("M18; - disable motors")); 233 | Serial.println(F("M100; - this help message")); 234 | Serial.println(F("M114; - report position and feedrate")); 235 | Serial.println(F("All commands must end with a newline.")); 236 | } 237 | 238 | 239 | /** 240 | * Read the input buffer and find any recognized commands. One G or M command per line. 241 | */ 242 | void processCommand() { 243 | int cmd = parseNumber('G',-1); 244 | switch(cmd) { 245 | case 0: 246 | case 1: { // line 247 | feedrate(parseNumber('F',fr)); 248 | line( parseNumber('X',(mode_abs?px:0)) + (mode_abs?0:px), 249 | parseNumber('Y',(mode_abs?py:0)) + (mode_abs?0:py) ); 250 | break; 251 | } 252 | case 2: 253 | case 3: { // arc 254 | feedrate(parseNumber('F',fr)); 255 | arc(parseNumber('I',(mode_abs?px:0)) + (mode_abs?0:px), 256 | parseNumber('J',(mode_abs?py:0)) + (mode_abs?0:py), 257 | parseNumber('X',(mode_abs?px:0)) + (mode_abs?0:px), 258 | parseNumber('Y',(mode_abs?py:0)) + (mode_abs?0:py), 259 | (cmd==2) ? -1 : 1); 260 | break; 261 | } 262 | case 4: pause(parseNumber('P',0)*1000); break; // dwell 263 | case 90: mode_abs=1; break; // absolute mode 264 | case 91: mode_abs=0; break; // relative mode 265 | case 92: // set logical position 266 | position( parseNumber('X',0), 267 | parseNumber('Y',0) ); 268 | break; 269 | default: break; 270 | } 271 | 272 | cmd = parseNumber('M',-1); 273 | switch(cmd) { 274 | case 18: // disable motors 275 | disable(); 276 | break; 277 | case 100: help(); break; 278 | case 114: where(); break; 279 | default: break; 280 | } 281 | } 282 | 283 | 284 | /** 285 | * prepares the input buffer to receive a new message and tells the serial connected device it is ready for more. 286 | */ 287 | void ready() { 288 | sofar=0; // clear input buffer 289 | Serial.print(F(">")); // signal ready to receive input 290 | } 291 | 292 | 293 | /** 294 | * First thing this machine does on startup. Runs only once. 295 | */ 296 | void setup() { 297 | Serial.begin(BAUD); // open coms 298 | 299 | setup_controller(); 300 | position(0,0); // set staring position 301 | feedrate((MAX_FEEDRATE + MIN_FEEDRATE)/2); // set default speed 302 | 303 | help(); // say hello 304 | ready(); 305 | } 306 | 307 | 308 | /** 309 | * After setup() this machine will repeat loop() forever. 310 | */ 311 | void loop() { 312 | // listen for serial commands 313 | while(Serial.available() > 0) { // if something is available 314 | char c=Serial.read(); // get it 315 | Serial.print(c); // repeat it back so I know you got the message 316 | if(sofar. 343 | */ 344 | -------------------------------------------------------------------------------- /arduino_libraries/Adafruit_MotorShield/Adafruit_MotorShield.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************** 2 | This is the library for the Adafruit Motor Shield V2 for Arduino. 3 | It supports DC motors & Stepper motors with microstepping as well 4 | as stacking-support. It is *not* compatible with the V1 library! 5 | 6 | It will only work with https://www.adafruit.com/products/1483 7 | 8 | Adafruit invests time and resources providing this open 9 | source code, please support Adafruit and open-source hardware 10 | by purchasing products from Adafruit! 11 | 12 | Written by Limor Fried/Ladyada for Adafruit Industries. 13 | BSD license, check license.txt for more information. 14 | All text above must be included in any redistribution. 15 | ******************************************************************/ 16 | 17 | 18 | #if (ARDUINO >= 100) 19 | #include "Arduino.h" 20 | #else 21 | #include "WProgram.h" 22 | #endif 23 | #include 24 | #include "Adafruit_MotorShield.h" 25 | #include 26 | #ifdef __AVR__ 27 | #define WIRE Wire 28 | #else // Arduino Due 29 | #define WIRE Wire1 30 | #endif 31 | 32 | 33 | #if (MICROSTEPS == 8) 34 | uint8_t microstepcurve[] = {0, 50, 98, 142, 180, 212, 236, 250, 255}; 35 | #elif (MICROSTEPS == 16) 36 | uint8_t microstepcurve[] = {0, 25, 50, 74, 98, 120, 141, 162, 180, 197, 212, 225, 236, 244, 250, 253, 255}; 37 | #endif 38 | 39 | Adafruit_MotorShield::Adafruit_MotorShield(uint8_t addr) { 40 | _addr = addr; 41 | _pwm = Adafruit_PWMServoDriver(_addr); 42 | } 43 | 44 | void Adafruit_MotorShield::begin(uint16_t freq) { 45 | // init PWM w/_freq 46 | WIRE.begin(); 47 | _pwm.begin(); 48 | _freq = freq; 49 | _pwm.setPWMFreq(_freq); // This is the maximum PWM frequency 50 | for (uint8_t i=0; i<16; i++) 51 | _pwm.setPWM(i, 0, 0); 52 | } 53 | 54 | void Adafruit_MotorShield::setPWM(uint8_t pin, uint16_t value) { 55 | if (value > 4095) { 56 | _pwm.setPWM(pin, 4096, 0); 57 | } else 58 | _pwm.setPWM(pin, 0, value); 59 | } 60 | void Adafruit_MotorShield::setPin(uint8_t pin, boolean value) { 61 | if (value == LOW) 62 | _pwm.setPWM(pin, 0, 0); 63 | else 64 | _pwm.setPWM(pin, 4096, 0); 65 | } 66 | 67 | Adafruit_DCMotor *Adafruit_MotorShield::getMotor(uint8_t num) { 68 | if (num > 4) return NULL; 69 | 70 | num--; 71 | 72 | if (dcmotors[num].motornum == 0) { 73 | // not init'd yet! 74 | dcmotors[num].motornum = num; 75 | dcmotors[num].MC = this; 76 | uint8_t pwm, in1, in2; 77 | if (num == 0) { 78 | pwm = 8; in2 = 9; in1 = 10; 79 | } else if (num == 1) { 80 | pwm = 13; in2 = 12; in1 = 11; 81 | } else if (num == 2) { 82 | pwm = 2; in2 = 3; in1 = 4; 83 | } else if (num == 3) { 84 | pwm = 7; in2 = 6; in1 = 5; 85 | } 86 | dcmotors[num].PWMpin = pwm; 87 | dcmotors[num].IN1pin = in1; 88 | dcmotors[num].IN2pin = in2; 89 | } 90 | return &dcmotors[num]; 91 | } 92 | 93 | 94 | Adafruit_StepperMotor *Adafruit_MotorShield::getStepper(uint16_t steps, uint8_t num) { 95 | if (num > 2) return NULL; 96 | 97 | num--; 98 | 99 | if (steppers[num].steppernum == 0) { 100 | // not init'd yet! 101 | steppers[num].steppernum = num; 102 | steppers[num].revsteps = steps; 103 | steppers[num].MC = this; 104 | uint8_t pwma, pwmb, ain1, ain2, bin1, bin2; 105 | if (num == 0) { 106 | pwma = 8; ain2 = 9; ain1 = 10; 107 | pwmb = 13; bin2 = 12; bin1 = 11; 108 | } else if (num == 1) { 109 | pwma = 2; ain2 = 3; ain1 = 4; 110 | pwmb = 7; bin2 = 6; bin1 = 5; 111 | } 112 | steppers[num].PWMApin = pwma; 113 | steppers[num].PWMBpin = pwmb; 114 | steppers[num].AIN1pin = ain1; 115 | steppers[num].AIN2pin = ain2; 116 | steppers[num].BIN1pin = bin1; 117 | steppers[num].BIN2pin = bin2; 118 | } 119 | return &steppers[num]; 120 | } 121 | 122 | 123 | /****************************************** 124 | MOTORS 125 | ******************************************/ 126 | 127 | Adafruit_DCMotor::Adafruit_DCMotor(void) { 128 | MC = NULL; 129 | motornum = 0; 130 | PWMpin = IN1pin = IN2pin = 0; 131 | } 132 | 133 | void Adafruit_DCMotor::run(uint8_t cmd) { 134 | switch (cmd) { 135 | case FORWARD: 136 | MC->setPin(IN2pin, LOW); // take low first to avoid 'break' 137 | MC->setPin(IN1pin, HIGH); 138 | break; 139 | case BACKWARD: 140 | MC->setPin(IN1pin, LOW); // take low first to avoid 'break' 141 | MC->setPin(IN2pin, HIGH); 142 | break; 143 | case RELEASE: 144 | MC->setPin(IN1pin, LOW); 145 | MC->setPin(IN2pin, LOW); 146 | break; 147 | } 148 | } 149 | 150 | void Adafruit_DCMotor::setSpeed(uint8_t speed) { 151 | MC->setPWM(PWMpin, speed*16); 152 | } 153 | 154 | /****************************************** 155 | STEPPERS 156 | ******************************************/ 157 | 158 | Adafruit_StepperMotor::Adafruit_StepperMotor(void) { 159 | revsteps = steppernum = currentstep = 0; 160 | } 161 | /* 162 | 163 | uint16_t steps, Adafruit_MotorShield controller) { 164 | 165 | revsteps = steps; 166 | steppernum = 1; 167 | currentstep = 0; 168 | 169 | if (steppernum == 1) { 170 | latch_state &= ~_BV(MOTOR1_A) & ~_BV(MOTOR1_B) & 171 | ~_BV(MOTOR2_A) & ~_BV(MOTOR2_B); // all motor pins to 0 172 | 173 | // enable both H bridges 174 | pinMode(11, OUTPUT); 175 | pinMode(3, OUTPUT); 176 | digitalWrite(11, HIGH); 177 | digitalWrite(3, HIGH); 178 | 179 | // use PWM for microstepping support 180 | MC->setPWM(1, 255); 181 | MC->setPWM(2, 255); 182 | 183 | } else if (steppernum == 2) { 184 | latch_state &= ~_BV(MOTOR3_A) & ~_BV(MOTOR3_B) & 185 | ~_BV(MOTOR4_A) & ~_BV(MOTOR4_B); // all motor pins to 0 186 | 187 | // enable both H bridges 188 | pinMode(5, OUTPUT); 189 | pinMode(6, OUTPUT); 190 | digitalWrite(5, HIGH); 191 | digitalWrite(6, HIGH); 192 | 193 | // use PWM for microstepping support 194 | // use PWM for microstepping support 195 | MC->setPWM(3, 255); 196 | MC->setPWM(4, 255); 197 | } 198 | } 199 | */ 200 | 201 | void Adafruit_StepperMotor::setSpeed(uint16_t rpm) { 202 | //Serial.println("steps per rev: "); Serial.println(revsteps); 203 | //Serial.println("RPM: "); Serial.println(rpm); 204 | 205 | usperstep = 60000000 / ((uint32_t)revsteps * (uint32_t)rpm); 206 | steppingcounter = 0; 207 | } 208 | 209 | void Adafruit_StepperMotor::release(void) { 210 | MC->setPin(AIN1pin, LOW); 211 | MC->setPin(AIN2pin, LOW); 212 | MC->setPin(BIN1pin, LOW); 213 | MC->setPin(BIN2pin, LOW); 214 | MC->setPWM(PWMApin, 0); 215 | MC->setPWM(PWMBpin, 0); 216 | } 217 | 218 | void Adafruit_StepperMotor::step(uint16_t steps, uint8_t dir, uint8_t style) { 219 | uint32_t uspers = usperstep; 220 | uint8_t ret = 0; 221 | 222 | if (style == INTERLEAVE) { 223 | uspers /= 2; 224 | } 225 | else if (style == MICROSTEP) { 226 | uspers /= MICROSTEPS; 227 | steps *= MICROSTEPS; 228 | #ifdef MOTORDEBUG 229 | Serial.print("steps = "); Serial.println(steps, DEC); 230 | #endif 231 | } 232 | 233 | while (steps--) { 234 | //Serial.println("step!"); Serial.println(uspers); 235 | ret = onestep(dir, style); 236 | delay(uspers/1000); // in ms 237 | steppingcounter += (uspers % 1000); 238 | if (steppingcounter >= 1000) { 239 | delay(1); 240 | steppingcounter -= 1000; 241 | } 242 | } 243 | if (style == MICROSTEP) { 244 | while ((ret != 0) && (ret != MICROSTEPS)) { 245 | ret = onestep(dir, style); 246 | delay(uspers/1000); // in ms 247 | steppingcounter += (uspers % 1000); 248 | if (steppingcounter >= 1000) { 249 | delay(1); 250 | steppingcounter -= 1000; 251 | } 252 | } 253 | } 254 | } 255 | 256 | uint8_t Adafruit_StepperMotor::onestep(uint8_t dir, uint8_t style) { 257 | uint8_t a, b, c, d; 258 | uint8_t ocrb, ocra; 259 | 260 | ocra = ocrb = 255; 261 | 262 | 263 | // next determine what sort of stepping procedure we're up to 264 | if (style == SINGLE) { 265 | if ((currentstep/(MICROSTEPS/2)) % 2) { // we're at an odd step, weird 266 | if (dir == FORWARD) { 267 | currentstep += MICROSTEPS/2; 268 | } 269 | else { 270 | currentstep -= MICROSTEPS/2; 271 | } 272 | } else { // go to the next even step 273 | if (dir == FORWARD) { 274 | currentstep += MICROSTEPS; 275 | } 276 | else { 277 | currentstep -= MICROSTEPS; 278 | } 279 | } 280 | } else if (style == DOUBLE) { 281 | if (! (currentstep/(MICROSTEPS/2) % 2)) { // we're at an even step, weird 282 | if (dir == FORWARD) { 283 | currentstep += MICROSTEPS/2; 284 | } else { 285 | currentstep -= MICROSTEPS/2; 286 | } 287 | } else { // go to the next odd step 288 | if (dir == FORWARD) { 289 | currentstep += MICROSTEPS; 290 | } else { 291 | currentstep -= MICROSTEPS; 292 | } 293 | } 294 | } else if (style == INTERLEAVE) { 295 | if (dir == FORWARD) { 296 | currentstep += MICROSTEPS/2; 297 | } else { 298 | currentstep -= MICROSTEPS/2; 299 | } 300 | } 301 | 302 | if (style == MICROSTEP) { 303 | if (dir == FORWARD) { 304 | currentstep++; 305 | } else { 306 | // BACKWARDS 307 | currentstep--; 308 | } 309 | 310 | currentstep += MICROSTEPS*4; 311 | currentstep %= MICROSTEPS*4; 312 | 313 | ocra = ocrb = 0; 314 | if ( (currentstep >= 0) && (currentstep < MICROSTEPS)) { 315 | ocra = microstepcurve[MICROSTEPS - currentstep]; 316 | ocrb = microstepcurve[currentstep]; 317 | } else if ( (currentstep >= MICROSTEPS) && (currentstep < MICROSTEPS*2)) { 318 | ocra = microstepcurve[currentstep - MICROSTEPS]; 319 | ocrb = microstepcurve[MICROSTEPS*2 - currentstep]; 320 | } else if ( (currentstep >= MICROSTEPS*2) && (currentstep < MICROSTEPS*3)) { 321 | ocra = microstepcurve[MICROSTEPS*3 - currentstep]; 322 | ocrb = microstepcurve[currentstep - MICROSTEPS*2]; 323 | } else if ( (currentstep >= MICROSTEPS*3) && (currentstep < MICROSTEPS*4)) { 324 | ocra = microstepcurve[currentstep - MICROSTEPS*3]; 325 | ocrb = microstepcurve[MICROSTEPS*4 - currentstep]; 326 | } 327 | } 328 | 329 | currentstep += MICROSTEPS*4; 330 | currentstep %= MICROSTEPS*4; 331 | 332 | #ifdef MOTORDEBUG 333 | Serial.print("current step: "); Serial.println(currentstep, DEC); 334 | Serial.print(" pwmA = "); Serial.print(ocra, DEC); 335 | Serial.print(" pwmB = "); Serial.println(ocrb, DEC); 336 | #endif 337 | MC->setPWM(PWMApin, ocra*17); 338 | MC->setPWM(PWMBpin, ocrb*17); 339 | 340 | 341 | // release all 342 | uint8_t latch_state = 0; // all motor pins to 0 343 | 344 | //Serial.println(step, DEC); 345 | if (style == MICROSTEP) { 346 | if ((currentstep >= 0) && (currentstep < MICROSTEPS)) 347 | latch_state |= 0x03; 348 | if ((currentstep >= MICROSTEPS) && (currentstep < MICROSTEPS*2)) 349 | latch_state |= 0x06; 350 | if ((currentstep >= MICROSTEPS*2) && (currentstep < MICROSTEPS*3)) 351 | latch_state |= 0x0C; 352 | if ((currentstep >= MICROSTEPS*3) && (currentstep < MICROSTEPS*4)) 353 | latch_state |= 0x09; 354 | } else { 355 | switch (currentstep/(MICROSTEPS/2)) { 356 | case 0: 357 | latch_state |= 0x1; // energize coil 1 only 358 | break; 359 | case 1: 360 | latch_state |= 0x3; // energize coil 1+2 361 | break; 362 | case 2: 363 | latch_state |= 0x2; // energize coil 2 only 364 | break; 365 | case 3: 366 | latch_state |= 0x6; // energize coil 2+3 367 | break; 368 | case 4: 369 | latch_state |= 0x4; // energize coil 3 only 370 | break; 371 | case 5: 372 | latch_state |= 0xC; // energize coil 3+4 373 | break; 374 | case 6: 375 | latch_state |= 0x8; // energize coil 4 only 376 | break; 377 | case 7: 378 | latch_state |= 0x9; // energize coil 1+4 379 | break; 380 | } 381 | } 382 | #ifdef MOTORDEBUG 383 | Serial.print("Latch: 0x"); Serial.println(latch_state, HEX); 384 | #endif 385 | 386 | if (latch_state & 0x1) { 387 | // Serial.println(AIN2pin); 388 | MC->setPin(AIN2pin, HIGH); 389 | } else { 390 | MC->setPin(AIN2pin, LOW); 391 | } 392 | if (latch_state & 0x2) { 393 | MC->setPin(BIN1pin, HIGH); 394 | // Serial.println(BIN1pin); 395 | } else { 396 | MC->setPin(BIN1pin, LOW); 397 | } 398 | if (latch_state & 0x4) { 399 | MC->setPin(AIN1pin, HIGH); 400 | // Serial.println(AIN1pin); 401 | } else { 402 | MC->setPin(AIN1pin, LOW); 403 | } 404 | if (latch_state & 0x8) { 405 | MC->setPin(BIN2pin, HIGH); 406 | // Serial.println(BIN2pin); 407 | } else { 408 | MC->setPin(BIN2pin, LOW); 409 | } 410 | 411 | return currentstep; 412 | } 413 | 414 | -------------------------------------------------------------------------------- /GcodeCNCDemo4AxisRAMPS/GcodeCNCDemo4AxisRAMPS.ino: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 4 Axis CNC Demo - supports MEGA 2560 Arduino RAMPS 1.4 3 | // dan@marginallyclever.com 2013-10-28 4 | // Modified by Søren Vedel 5 | // sorenvedel@gmail.com 2015-06-19 6 | //------------------------------------------------------------------------------ 7 | // Copyright at end of file. 8 | // please see http://www.github.com/MarginallyClever/GcodeCNCDemo for more information. 9 | 10 | 11 | //------------------------------------------------------------------------------ 12 | // CONSTANTS 13 | //------------------------------------------------------------------------------ 14 | //#define VERBOSE (1) // add to get a lot more serial output. 15 | 16 | #define VERSION (2) // firmware version 17 | #define BAUD (57600) // How fast is the Arduino talking? 18 | #define MAX_BUF (64) // What is the longest message Arduino can store? 19 | #define STEPS_PER_TURN (400) // depends on your stepper motor. most are 200. 20 | #define STEPS_PER_MM (STEPS_PER_TURN*16/1.25) // (400*16)/1.25 with a M8 spindle 21 | #define MAX_FEEDRATE (1000000) 22 | #define MIN_FEEDRATE (1) 23 | #define NUM_AXIES (4) 24 | 25 | 26 | //------------------------------------------------------------------------------ 27 | // STRUCTS 28 | //------------------------------------------------------------------------------ 29 | // for line() 30 | typedef struct { 31 | long delta; // number of steps to move 32 | long absdelta; 33 | long over; // for dx/dy bresenham calculations 34 | } Axis; 35 | 36 | 37 | typedef struct { 38 | int step_pin; 39 | int dir_pin; 40 | int enable_pin; 41 | int limit_switch_pin; 42 | } Motor; 43 | 44 | 45 | //------------------------------------------------------------------------------ 46 | // GLOBALS 47 | //------------------------------------------------------------------------------ 48 | Axis a[NUM_AXIES]; // for line() 49 | Axis atemp; // for line() 50 | Motor motors[NUM_AXIES]; 51 | 52 | char serialBuffer[MAX_BUF]; // where we store the message until we get a ';' 53 | int sofar; // how much is in the buffer 54 | 55 | // speeds 56 | float fr=0; // human version 57 | long step_delay; // machine version 58 | 59 | float px,py,pz,pe; // position 60 | 61 | // settings 62 | char mode_abs=1; // absolute mode? 63 | 64 | long line_number=0; 65 | 66 | 67 | //------------------------------------------------------------------------------ 68 | // METHODS 69 | //------------------------------------------------------------------------------ 70 | 71 | 72 | /** 73 | * delay for the appropriate number of microseconds 74 | * @input ms how many milliseconds to wait 75 | */ 76 | void pause(long ms) { 77 | delay(ms/1000); 78 | delayMicroseconds(ms%1000); // delayMicroseconds doesn't work for values > ~16k. 79 | } 80 | 81 | 82 | /** 83 | * Set the feedrate (speed motors will move) 84 | * @input nfr the new speed in steps/second 85 | */ 86 | void feedrate(float nfr) { 87 | if(fr==nfr) return; // same as last time? quit now. 88 | 89 | if(nfr>MAX_FEEDRATE || nfr0?HIGH:LOW); 150 | } 151 | for(i=0;i maxsteps/2 ) 159 | steps_to_accel = maxsteps/2; 160 | 161 | long steps_to_decel = maxsteps - steps_to_accel; 162 | 163 | Serial.print("START "); 164 | Serial.println(dt); 165 | Serial.print("TOP "); 166 | Serial.println(step_delay); 167 | 168 | Serial.print("accel until "); 169 | Serial.println(steps_to_accel); 170 | Serial.print("decel after "); 171 | Serial.println(steps_to_decel); 172 | Serial.print("total "); 173 | Serial.println(maxsteps); 174 | #ifdef VERBOSE 175 | Serial.println(F("Start >")); 176 | #endif 177 | 178 | for( i=0; i= maxsteps) { 182 | a[j].over -= maxsteps; 183 | 184 | digitalWrite(motors[j].step_pin,HIGH); 185 | digitalWrite(motors[j].step_pin,LOW); 186 | } 187 | } 188 | 189 | if(i=steps_to_decel) { 193 | dt += accel; 194 | } 195 | delayMicroseconds(dt); 196 | } 197 | 198 | #ifdef VERBOSE 199 | Serial.println(F("< Done.")); 200 | #endif 201 | 202 | position(newx,newy,newz,newe); 203 | 204 | where(); 205 | } 206 | 207 | 208 | // returns angle of dy/dx as a value from 0...2PI 209 | static float atan3(float dy,float dx) { 210 | float a=atan2(dy,dx); 211 | if(a<0) a=(PI*2.0)+a; 212 | return a; 213 | } 214 | 215 | 216 | 217 | /** 218 | * Look for character /code/ in the serialBuffer and read the float that immediately follows it. 219 | * @return the value found. If nothing is found, /val/ is returned. 220 | * @input code the character to look for. 221 | * @input val the return value if /code/ is not found. 222 | **/ 223 | float parseNumber(char code,float val) { 224 | char *ptr=serialBuffer; // start at the beginning of serialBuffer 225 | while((long)ptr > 1 && (*ptr) && (long)ptr < (long)serialBuffer+sofar) { // walk to the end 226 | if(*ptr==code) { // if you find code on your walk, 227 | return atof(ptr+1); // convert the digits that follow into a float and return it 228 | } 229 | ptr=strchr(ptr,' ')+1; // take a step from here to the letter after the next space 230 | } 231 | return val; // end reached, nothing found, return default val. 232 | } 233 | 234 | 235 | 236 | /** 237 | * write a string followed by a float to the serial line. Convenient for debugging. 238 | * @input code the string. 239 | * @input val the float. 240 | */ 241 | void output(const char *code,float val) { 242 | Serial.print(code); 243 | Serial.println(val); 244 | } 245 | 246 | 247 | /** 248 | * print the current position, feedrate, and absolute mode. 249 | */ 250 | void where() { 251 | output("X",px); 252 | output("Y",py); 253 | output("Z",pz); 254 | output("E",pe); 255 | output("F",fr); 256 | Serial.println(mode_abs?"ABS":"REL"); 257 | } 258 | 259 | 260 | /** 261 | * display helpful information 262 | */ 263 | void help() { 264 | Serial.print(F("GcodeCNCDemo6AxisV2 ")); 265 | Serial.println(VERSION); 266 | Serial.println(F("Commands:")); 267 | Serial.println(F("G00/G01 [X/Y/Z/E(steps)] [F(feedrate)]; - linear move")); 268 | Serial.println(F("G04 P[seconds]; - delay")); 269 | Serial.println(F("G90; - absolute mode")); 270 | Serial.println(F("G91; - relative mode")); 271 | Serial.println(F("G92 [X/Y/Z/E(steps)]; - change logical position")); 272 | Serial.println(F("M18; - disable motors")); 273 | Serial.println(F("M100; - this help message")); 274 | Serial.println(F("M114; - report position and feedrate")); 275 | Serial.println(F("All commands must end with a newline.")); 276 | } 277 | 278 | 279 | /** 280 | * Read the serialBuffer and find any recognized commands. One G or M command per line. 281 | */ 282 | void processCommand() { 283 | int cmd = parseNumber('G',-1); 284 | switch(cmd) { 285 | case 0: 286 | case 1: { // line 287 | feedrate(parseNumber('F',fr)); 288 | line( parseNumber('X',(mode_abs?px:0)) + (mode_abs?0:px), 289 | parseNumber('Y',(mode_abs?py:0)) + (mode_abs?0:py), 290 | parseNumber('Z',(mode_abs?pz:0)) + (mode_abs?0:pz), 291 | parseNumber('E',(mode_abs?pe:0)) + (mode_abs?0:pe) ); 292 | break; 293 | } 294 | case 2: 295 | case 4: pause(parseNumber('P',0)*1000); break; // dwell 296 | case 90: mode_abs=1; break; // absolute mode 297 | case 91: mode_abs=0; break; // relative mode 298 | case 92: // set logical position 299 | position( parseNumber('X',0), 300 | parseNumber('Y',0), 301 | parseNumber('Z',0), 302 | parseNumber('E',0) ); 303 | break; 304 | default: break; 305 | } 306 | 307 | cmd = parseNumber('M',-1); 308 | switch(cmd) { 309 | case 17: motor_enable(); break; 310 | case 18: motor_disable(); break; 311 | case 100: help(); break; 312 | case 114: where(); break; 313 | default: break; 314 | } 315 | } 316 | 317 | 318 | /** 319 | * prepares the serialBuffer to receive a new message and tells the serial connected device it is ready for more. 320 | */ 321 | void ready() { 322 | sofar=0; // clear serialBuffer 323 | Serial.print(F(">")); // signal ready to receive input 324 | } 325 | 326 | 327 | /** 328 | * set up the pins for each motor 329 | * Pins fits a Ramps 1.4 board 330 | */ 331 | void motor_setup() { 332 | motors[0].step_pin=54; 333 | motors[0].dir_pin=55; 334 | motors[0].enable_pin=38; 335 | motors[0].limit_switch_pin=3; 336 | 337 | motors[1].step_pin=60; 338 | motors[1].dir_pin=61; 339 | motors[1].enable_pin=56; 340 | motors[1].limit_switch_pin=14; 341 | 342 | motors[2].step_pin=46; 343 | motors[2].dir_pin=48; 344 | motors[2].enable_pin=62; 345 | motors[2].limit_switch_pin=18; 346 | 347 | motors[3].step_pin=26; 348 | motors[3].dir_pin=28; 349 | motors[3].enable_pin=24; 350 | motors[3].limit_switch_pin=34; 351 | 352 | int i; 353 | for(i=0;i 0) { // if something is available 402 | char c=Serial.read(); // get it 403 | Serial.print(c); // repeat it back so I know you got the message 404 | if(sofar. 431 | */ 432 | -------------------------------------------------------------------------------- /GcodeCNCDemo4AxisCNCShield/GcodeCNCDemo4AxisCNCShield.ino: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 4 Axis CNC Demo - supports CNCShieldV3 on arduino UNO 3 | // dan@marginallyclever.com 2013-10-28 4 | // Modified by Søren Vedel 5 | // sorenvedel@gmail.com 2015-06-19 6 | // Modified by Cristian Leiva 7 | // cristianleiva@gmail.com 2016-04-28 8 | // add Support cncshield - feed rate in mm/min 9 | 10 | //------------------------------------------------------------------------------ 11 | // Copyright at end of file. 12 | // please see http://www.github.com/MarginallyClever/GcodeCNCDemo for more information. 13 | 14 | 15 | //------------------------------------------------------------------------------ 16 | // CONSTANTS 17 | //------------------------------------------------------------------------------ 18 | //#define VERBOSE (1) // add to get a lot more serial output. 19 | 20 | #define VERSION (2) // firmware version 21 | #define BAUD (115200) // How fast is the Arduino talking?(BAUD Rate of Arduino) 22 | #define MAX_BUF (64) // What is the longest message Arduino can store? 23 | #define STEPS_PER_TURN (200) // depends on your stepper motor. most are 200. 24 | #define STEPS_PER_MM (STEPS_PER_TURN*16/0.8) // (400*16)/0.8 with a M5 spindle 25 | #define MAX_FEEDRATE (1000000) 26 | #define MIN_FEEDRATE (1) 27 | #define NUM_AXIES (4) 28 | 29 | 30 | //------------------------------------------------------------------------------ 31 | // STRUCTS 32 | //------------------------------------------------------------------------------ 33 | // for line() 34 | typedef struct { 35 | long delta; // number of steps to move 36 | long absdelta; 37 | long over; // for dx/dy bresenham calculations 38 | } Axis; 39 | 40 | 41 | typedef struct { 42 | int step_pin; 43 | int dir_pin; 44 | int enable_pin; 45 | int limit_switch_pin; 46 | } Motor; 47 | 48 | 49 | //------------------------------------------------------------------------------ 50 | // GLOBALS 51 | //------------------------------------------------------------------------------ 52 | Axis a[NUM_AXIES]; // for line() 53 | Axis atemp; // for line() 54 | Motor motors[NUM_AXIES]; 55 | 56 | char buffer[MAX_BUF]; // where we store the message until we get a ';' 57 | int sofar; // how much is in the buffer 58 | 59 | // speeds 60 | float fr=0; // human version 61 | long step_delay; // machine version 62 | 63 | float px,py,pz,pe; // position 64 | 65 | // settings 66 | char mode_abs=1; // absolute mode? 67 | 68 | long line_number=0; 69 | 70 | 71 | //------------------------------------------------------------------------------ 72 | // METHODS 73 | //------------------------------------------------------------------------------ 74 | 75 | 76 | /** 77 | * delay for the appropriate number of microseconds 78 | * @input ms how many milliseconds to wait 79 | */ 80 | void pause(long ms) { 81 | delay(ms/1000); 82 | delayMicroseconds(ms%1000); // delayMicroseconds doesn't work for values > ~16k. 83 | } 84 | 85 | 86 | /** 87 | * Set the feedrate (speed motors will move) 88 | * @input nfr the new speed in steps/second 89 | */ 90 | void feedrate(float nfr) { 91 | nfr = nfr*STEPS_PER_MM/60; 92 | if(fr==nfr) return; // same as last time? quit now. 93 | 94 | if(nfr>MAX_FEEDRATE || nfr0?HIGH:LOW); 156 | } 157 | 158 | long dt = MAX_FEEDRATE/5000; 159 | long accel = 1; 160 | long steps_to_accel = dt - step_delay; 161 | if(steps_to_accel > maxsteps/2 ) 162 | steps_to_accel = maxsteps/2; 163 | 164 | long steps_to_decel = maxsteps - steps_to_accel; 165 | 166 | Serial.print("START "); 167 | Serial.println(dt); 168 | Serial.print("STOP "); 169 | Serial.println(step_delay); 170 | 171 | Serial.print("accel until "); 172 | Serial.println(steps_to_accel); 173 | Serial.print("decel after "); 174 | Serial.println(steps_to_decel); 175 | Serial.print("total "); 176 | Serial.println(maxsteps); 177 | #ifdef VERBOSE 178 | Serial.println(F("Start >")); 179 | #endif 180 | 181 | for( i=0; i= maxsteps) { 185 | a[j].over -= maxsteps; 186 | 187 | digitalWrite(motors[j].step_pin,HIGH); 188 | digitalWrite(motors[j].step_pin,LOW); 189 | } 190 | } 191 | 192 | if(i=steps_to_decel) { 196 | dt += accel; 197 | } 198 | delayMicroseconds(dt); 199 | } 200 | 201 | #ifdef VERBOSE 202 | Serial.println(F("< Done.")); 203 | #endif 204 | 205 | position(newx,newy,newz,newe); 206 | 207 | where(); 208 | } 209 | 210 | 211 | // returns angle of dy/dx as a value from 0...2PI 212 | static float atan3(float dy,float dx) { 213 | float a=atan2(dy,dx); 214 | if(a<0) a=(PI*2.0)+a; 215 | return a; 216 | } 217 | 218 | 219 | 220 | /** 221 | * Look for character /code/ in the buffer and read the float that immediately follows it. 222 | * @return the value found. If nothing is found, /val/ is returned. 223 | * @input code the character to look for. 224 | * @input val the return value if /code/ is not found. 225 | **/ 226 | float parseNumber(char code,float val) { 227 | char *ptr=buffer; // start at the beginning of buffer 228 | while((long)ptr > 1 && (*ptr) && (long)ptr < (long)buffer+sofar) { // walk to the end 229 | if(*ptr==code) { // if you find code on your walk, 230 | return atof(ptr+1); // convert the digits that follow into a float and return it 231 | } 232 | ptr=strchr(ptr,' ')+1; // take a step from here to the letter after the next space 233 | } 234 | return val; // end reached, nothing found, return default val. 235 | } 236 | 237 | 238 | /** 239 | * write a string followed by a float to the serial line. Convenient for debugging. 240 | * @input code the string. 241 | * @input val the float. 242 | */ 243 | void output(char *code,float val) { 244 | Serial.print(code); 245 | Serial.print(val); 246 | Serial.print(" "); 247 | } 248 | 249 | 250 | /** 251 | * print the current position, feedrate, and absolute mode. 252 | */ 253 | void where() { 254 | output("X",px); 255 | output("Y",py); 256 | output("Z",pz); 257 | output("E",pe); 258 | output("F",fr/STEPS_PER_MM*60); 259 | Serial.println(mode_abs?"ABS":"REL"); 260 | } 261 | 262 | 263 | /** 264 | * display helpful information 265 | */ 266 | void help() { 267 | Serial.print(F("GcodeCNCDemo6AxisV2 ")); 268 | Serial.println(VERSION); 269 | Serial.println(F("Commands:")); 270 | Serial.println(F("G00/G01 [X/Y/Z/E(steps)] [F(feedrate)]; - linear move")); 271 | Serial.println(F("G04 P[seconds]; - delay")); 272 | Serial.println(F("G90; - absolute mode")); 273 | Serial.println(F("G91; - relative mode")); 274 | Serial.println(F("G92 [X/Y/Z/E(steps)]; - change logical position")); 275 | Serial.println(F("M18; - disable motors")); 276 | Serial.println(F("M100; - this help message")); 277 | Serial.println(F("M114; - report position and feedrate")); 278 | Serial.println(F("All commands must end with a newline.")); 279 | } 280 | 281 | 282 | /** 283 | * Read the input buffer and find any recognized commands. One G or M command per line. 284 | */ 285 | void processCommand() { 286 | int cmd = parseNumber('G',-1); 287 | switch(cmd) { 288 | case 0: 289 | case 1: { // line 290 | feedrate(parseNumber('F',fr)); 291 | line( parseNumber('X',(mode_abs?px:0)) + (mode_abs?0:px), 292 | parseNumber('Y',(mode_abs?py:0)) + (mode_abs?0:py), 293 | parseNumber('Z',(mode_abs?pz:0)) + (mode_abs?0:pz), 294 | parseNumber('E',(mode_abs?pe:0)) + (mode_abs?0:pe) ); 295 | break; 296 | } 297 | case 2: 298 | case 4: pause(parseNumber('P',0)*1000); break; // dwell 299 | case 90: mode_abs=1; break; // absolute mode 300 | case 91: mode_abs=0; break; // relative mode 301 | case 92: // set logical position 302 | position( parseNumber('X',0), 303 | parseNumber('Y',0), 304 | parseNumber('Z',0), 305 | parseNumber('E',0) ); 306 | break; 307 | default: break; 308 | } 309 | 310 | cmd = parseNumber('M',-1); 311 | switch(cmd) { 312 | case 17: motor_enable(); break; 313 | case 18: motor_disable(); break; 314 | case 100: help(); break; 315 | case 114: where(); break; 316 | default: break; 317 | } 318 | } 319 | 320 | 321 | /** 322 | * prepares the input buffer to receive a new message and tells the serial connected device it is ready for more. 323 | */ 324 | void ready() { 325 | sofar=0; // clear input buffer 326 | Serial.print(F(">")); // signal ready to receive input 327 | } 328 | 329 | 330 | /** 331 | * set up the pins for each motor 332 | * Pins fits a CNCshieldV3.xx 333 | */ 334 | void motor_setup() { 335 | motors[0].step_pin=2; 336 | motors[0].dir_pin=5; 337 | motors[0].enable_pin=8; 338 | motors[0].limit_switch_pin=9; 339 | 340 | motors[1].step_pin=3; 341 | motors[1].dir_pin=6; 342 | motors[1].enable_pin=8; 343 | motors[1].limit_switch_pin=10; 344 | 345 | motors[2].step_pin=4; 346 | motors[2].dir_pin=7; 347 | motors[2].enable_pin=8; 348 | motors[2].limit_switch_pin=11; 349 | 350 | motors[3].step_pin=12; 351 | motors[3].dir_pin=13; 352 | motors[3].enable_pin=8; 353 | motors[3].limit_switch_pin=11; 354 | 355 | int i; 356 | for(i=0;i 0) { // if something is available 405 | char c=Serial.read(); // get it 406 | Serial.print(c); // repeat it back so I know you got the message 407 | if(sofar. 434 | */ 435 | -------------------------------------------------------------------------------- /GcodeCNCDemo6AxisV2/GcodeCNCDemo6AxisV2.ino: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 6 Axis CNC Demo v2 - supports Adafruit motor shield v2 3 | // dan@marginallyclever.com 2013-09-07 4 | //------------------------------------------------------------------------------ 5 | // Copyright at end of file. 6 | // please see http://www.github.com/MarginallyClever/GcodeCNCDemo for more information. 7 | 8 | 9 | //------------------------------------------------------------------------------ 10 | // CONSTANTS 11 | //------------------------------------------------------------------------------ 12 | //#define VERBOSE (1) // add to get a lot more serial output. 13 | 14 | #define VERSION (2) // firmware version 15 | #define BAUD (57600) // How fast is the Arduino talking? 16 | #define MAX_BUF (64) // What is the longest message Arduino can store? 17 | #define STEPS_PER_TURN (400) // depends on your stepper motor. most are 200. 18 | #define MIN_STEP_DELAY (50) // Minimum stepper motor delay. 19 | #define MAX_FEEDRATE (1000000/MIN_STEP_DELAY) 20 | #define MIN_FEEDRATE (0.01) 21 | #define NUM_AXIES (6) // Six-Axies 22 | //#define INVERT_012 (1) // invert direction for Axes 0,1,2 23 | 24 | 25 | // for arc directions 26 | #define ARC_CW (1) 27 | #define ARC_CCW (-1) 28 | // Arcs are split into many line segments. How long are the segments? 29 | #define MM_PER_SEGMENT (10) 30 | 31 | 32 | //------------------------------------------------------------------------------ 33 | // INCLUDES 34 | //------------------------------------------------------------------------------ 35 | #include 36 | #include 37 | #include "utility/Adafruit_PWMServoDriver.h" 38 | 39 | 40 | //------------------------------------------------------------------------------ 41 | // STRUCTS 42 | //------------------------------------------------------------------------------ 43 | // for line() 44 | typedef struct { 45 | long delta; 46 | long absdelta; 47 | int dir; 48 | long over; 49 | } Axis; 50 | 51 | 52 | 53 | //------------------------------------------------------------------------------ 54 | // GLOBALS 55 | //------------------------------------------------------------------------------ 56 | // Initialize Adafruit stepper controller 57 | Adafruit_MotorShield AFMS0 = Adafruit_MotorShield(0x61); 58 | Adafruit_MotorShield AFMS1 = Adafruit_MotorShield(0x60); 59 | Adafruit_MotorShield AFMS2 = Adafruit_MotorShield(0x63); 60 | // Connect stepper motors with 400 steps per revolution (1.8 degree) 61 | // Create the motor shield object with the default I2C address 62 | Adafruit_StepperMotor *m[NUM_AXIES]; 63 | 64 | 65 | Axis a[NUM_AXIES]; // for line() 66 | Axis atemp; // for line() 67 | 68 | char serialBuffer[MAX_BUF]; // where we store the message until we get a ';' 69 | int sofar; // how much is in the buffer 70 | 71 | // speeds 72 | float fr=0; // human version 73 | long step_delay; // machine version 74 | 75 | float px,py,pz,pu,pv,pw; // position 76 | 77 | // settings 78 | char mode_abs=1; // absolute mode? 79 | 80 | long line_number=0; 81 | 82 | //------------------------------------------------------------------------------ 83 | // METHODS 84 | //------------------------------------------------------------------------------ 85 | 86 | 87 | /** 88 | * delay for the appropriate number of microseconds 89 | * @input ms how many milliseconds to wait 90 | */ 91 | void pause(long ms) { 92 | delay(ms/1000); 93 | delayMicroseconds(ms%1000); // delayMicroseconds doesn't work for values > ~16k. 94 | } 95 | 96 | 97 | /** 98 | * Set the feedrate (speed motors will move) 99 | * @input nfr the new speed in steps/second 100 | */ 101 | void feedrate(float nfr) { 102 | if(fr==nfr) return; // same as last time? quit now. 103 | 104 | if(nfr>MAX_FEEDRATE || nfronestep(direction>0?FORWARD:BACKWARD,MICROSTEP); 144 | m[motor]->onestep(direction>0?FORWARD:BACKWARD,INTERLEAVE); 145 | } 146 | 147 | 148 | /** 149 | * Releases the power on the motors 150 | **/ 151 | void release() { 152 | int i; 153 | for(i=0;irelease(); 155 | } 156 | } 157 | 158 | 159 | /** 160 | * Uses bresenham's line algorithm to move both motors 161 | * @input newx the destination x position 162 | * @input newy the destination y position 163 | **/ 164 | void line(float newx,float newy,float newz,float newu,float newv,float neww) { 165 | a[0].delta = newx-px; 166 | a[1].delta = newy-py; 167 | a[2].delta = newz-pz; 168 | a[3].delta = newu-pu; 169 | a[4].delta = newv-pv; 170 | a[5].delta = neww-pw; 171 | 172 | long i,j,maxsteps=0; 173 | 174 | for(i=0;i 0 ? 1:-1; 176 | a[i].absdelta = abs(a[i].delta); 177 | if( maxsteps < a[i].absdelta ) maxsteps = a[i].absdelta; 178 | } 179 | for(i=0;i")); 191 | #endif 192 | 193 | for( i=0; i= maxsteps) { 197 | a[j].over -= maxsteps; 198 | onestep(j,a[j].dir); 199 | } 200 | } 201 | pause(step_delay); 202 | } 203 | 204 | #ifdef VERBOSE 205 | Serial.println(F("< Done.")); 206 | #endif 207 | 208 | position(newx,newy,newz,newu,newv,neww); 209 | } 210 | 211 | 212 | // returns angle of dy/dx as a value from 0...2PI 213 | static float atan3(float dy,float dx) { 214 | float a=atan2(dy,dx); 215 | if(a<0) a=(PI*2.0)+a; 216 | return a; 217 | } 218 | 219 | 220 | // This method assumes the limits have already been checked. 221 | // This method assumes the start and end radius match. 222 | // This method assumes arcs are not >180 degrees (PI radians) 223 | // cx/cy - center of circle 224 | // x/y - end position 225 | // dir - ARC_CW or ARC_CCW to control direction of arc 226 | static void arc(float cx,float cy,float x,float y,float dir) { 227 | // get radius 228 | float dx = px - cx; 229 | float dy = py - cy; 230 | float radius=sqrt(dx*dx+dy*dy); 231 | 232 | // find angle of arc (sweep) 233 | float angle1=atan3(dy,dx); 234 | float angle2=atan3(y-cy,x-cx); 235 | float theta=angle2-angle1; 236 | 237 | if(dir>0 && theta<0) angle2+=2*PI; 238 | else if(dir<0 && theta>0) angle1+=2*PI; 239 | 240 | theta=angle2-angle1; 241 | 242 | // get length of arc 243 | // float circ=PI*2.0*radius; 244 | // float len=theta*circ/(PI*2.0); 245 | // simplifies to 246 | float len = abs(theta) * radius; 247 | 248 | int i, segments = ceil( len * MM_PER_SEGMENT ); 249 | 250 | float nx, ny, angle3, scale; 251 | 252 | for(i=0;i 1 && (*ptr) && (long)ptr < (long)serialBuffer+sofar) { // walk to the end 276 | if(*ptr==code) { // if you find code on your walk, 277 | return atof(ptr+1); // convert the digits that follow into a float and return it 278 | } 279 | ptr=strchr(ptr,' ')+1; // take a step from here to the letter after the next space 280 | } 281 | return val; // end reached, nothing found, return default val. 282 | } 283 | 284 | 285 | /** 286 | * write a string followed by a float to the serial line. Convenient for debugging. 287 | * @input code the string. 288 | * @input val the float. 289 | */ 290 | void output(char *code,float val) { 291 | Serial.print(code); 292 | Serial.println(val); 293 | } 294 | 295 | 296 | /** 297 | * print the current position, feedrate, and absolute mode. 298 | */ 299 | void where() { 300 | output("X",px); 301 | output("Y",py); 302 | output("Z",pz); 303 | output("U",pu); 304 | output("V",pv); 305 | output("W",pw); 306 | output("F",fr); 307 | Serial.println(mode_abs?"ABS":"REL"); 308 | } 309 | 310 | 311 | /** 312 | * display helpful information 313 | */ 314 | void help() { 315 | Serial.print(F("GcodeCNCDemo6AxisV2 ")); 316 | Serial.println(VERSION); 317 | Serial.println(F("Commands:")); 318 | Serial.println(F("G00/G01 [X/Y/Z/U/V/W(steps)] [F(feedrate)]; - linear move")); 319 | Serial.println(F("G02 [X(steps)] [Y(steps)] [I(steps)] [J(steps)] [F(feedrate)]; - clockwise arc")); 320 | Serial.println(F("G03 [X(steps)] [Y(steps)] [I(steps)] [J(steps)] [F(feedrate)]; - counter-clockwise arc")); 321 | Serial.println(F("G04 P[seconds]; - delay")); 322 | Serial.println(F("G90; - absolute mode")); 323 | Serial.println(F("G91; - relative mode")); 324 | Serial.println(F("G92 [X/Y/Z/U/V/W(steps)]; - change logical position")); 325 | Serial.println(F("M18; - disable motors")); 326 | Serial.println(F("M100; - this help message")); 327 | Serial.println(F("M114; - report position and feedrate")); 328 | Serial.println(F("All commands must end with a newline.")); 329 | } 330 | 331 | 332 | /** 333 | * Read the input buffer and find any recognized commands. One G or M command per line. 334 | */ 335 | void processCommand() { 336 | int cmd = parseNumber('G',-1); 337 | switch(cmd) { 338 | case 0: 339 | case 1: { // line 340 | feedrate(parseNumber('F',fr)); 341 | line( parseNumber('X',(mode_abs?px:0)) + (mode_abs?0:px), 342 | parseNumber('Y',(mode_abs?py:0)) + (mode_abs?0:py), 343 | parseNumber('Z',(mode_abs?pz:0)) + (mode_abs?0:pz), 344 | parseNumber('U',(mode_abs?pu:0)) + (mode_abs?0:pu), 345 | parseNumber('V',(mode_abs?pv:0)) + (mode_abs?0:pv), 346 | parseNumber('W',(mode_abs?pw:0)) + (mode_abs?0:pw) ); 347 | break; 348 | } 349 | case 2: 350 | case 3: { // arc 351 | feedrate(parseNumber('F',fr)); 352 | arc(parseNumber('I',(mode_abs?px:0)) + (mode_abs?0:px), 353 | parseNumber('J',(mode_abs?py:0)) + (mode_abs?0:py), 354 | parseNumber('X',(mode_abs?px:0)) + (mode_abs?0:px), 355 | parseNumber('Y',(mode_abs?py:0)) + (mode_abs?0:py), 356 | (cmd==2) ? -1 : 1); 357 | break; 358 | } 359 | case 4: pause(parseNumber('P',0)*1000); break; // dwell 360 | case 90: mode_abs=1; break; // absolute mode 361 | case 91: mode_abs=0; break; // relative mode 362 | case 92: // set logical position 363 | position( parseNumber('X',0), 364 | parseNumber('Y',0), 365 | parseNumber('Z',0), 366 | parseNumber('U',0), 367 | parseNumber('V',0), 368 | parseNumber('W',0) ); 369 | break; 370 | default: break; 371 | } 372 | 373 | cmd = parseNumber('M',-1); 374 | switch(cmd) { 375 | case 18: // disable motors 376 | release(); 377 | break; 378 | case 100: help(); break; 379 | case 114: where(); break; 380 | default: break; 381 | } 382 | } 383 | 384 | 385 | /** 386 | * prepares the input buffer to receive a new message and tells the serial connected device it is ready for more. 387 | */ 388 | void ready() { 389 | sofar=0; // clear input buffer 390 | Serial.print(F(">")); // signal ready to receive input 391 | } 392 | 393 | 394 | /** 395 | * First thing this machine does on startup. Runs only once. 396 | */ 397 | void setup() { 398 | Serial.begin(BAUD); // open coms 399 | 400 | AFMS0.begin(); // Start the shields 401 | AFMS1.begin(); 402 | AFMS2.begin(); 403 | 404 | m[0] = AFMS0.getStepper(STEPS_PER_TURN, 1); 405 | m[1] = AFMS0.getStepper(STEPS_PER_TURN, 2); 406 | m[2] = AFMS1.getStepper(STEPS_PER_TURN, 1); 407 | m[3] = AFMS1.getStepper(STEPS_PER_TURN, 2); 408 | m[4] = AFMS2.getStepper(STEPS_PER_TURN, 1); 409 | m[5] = AFMS2.getStepper(STEPS_PER_TURN, 2); 410 | 411 | help(); // say hello 412 | position(0,0,0,0,0,0); // set staring position 413 | feedrate(200); // set default speed 414 | ready(); 415 | } 416 | 417 | 418 | /** 419 | * After setup() this machine will repeat loop() forever. 420 | */ 421 | void loop() { 422 | // listen for serial commands 423 | while(Serial.available() > 0) { // if something is available 424 | char c=Serial.read(); // get it 425 | Serial.print(c); // repeat it back so I know you got the message 426 | if(sofar. 453 | */ 454 | -------------------------------------------------------------------------------- /GcodeCNCDemo4axisV2/GcodeCNCDemo4AxisV2.ino: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 4 Axis CNC Demo v2 - supports Adafruit motor shield v2 3 | // dan@marginallyclever.com 2013-08-30 4 | //------------------------------------------------------------------------------ 5 | // Copyright at end of file. 6 | // please see http://www.github.com/MarginallyClever/GcodeCNCDemo for more information. 7 | 8 | 9 | //------------------------------------------------------------------------------ 10 | // CONSTANTS 11 | //------------------------------------------------------------------------------ 12 | //#define VERBOSE (1) // add to get a lot more serial output. 13 | 14 | #define VERSION (2) // firmware version 15 | #define BAUD (57600) // How fast is the Arduino talking? 16 | #define MAX_BUF (64) // What is the longest message Arduino can store? 17 | #define STEPS_PER_TURN (400) // depends on your stepper motor. most are 200. 18 | #define MIN_STEP_DELAY (50) 19 | #define MAX_FEEDRATE (1000000/MIN_STEP_DELAY) 20 | #define MIN_FEEDRATE (0.01) 21 | #define NUM_AXIES (4) 22 | 23 | // for arc directions 24 | #define ARC_CW (1) 25 | #define ARC_CCW (-1) 26 | // Arcs are split into many line segments. How long are the segments? 27 | #define MM_PER_SEGMENT (10) 28 | 29 | 30 | //------------------------------------------------------------------------------ 31 | // INCLUDES 32 | //------------------------------------------------------------------------------ 33 | #include 34 | #include 35 | #include "utility/Adafruit_PWMServoDriver.h" 36 | 37 | 38 | //------------------------------------------------------------------------------ 39 | // STRUCTS 40 | //------------------------------------------------------------------------------ 41 | // for line() 42 | typedef struct { 43 | long delta; 44 | long absdelta; 45 | int dir; 46 | long over; 47 | } Axis; 48 | 49 | 50 | 51 | //------------------------------------------------------------------------------ 52 | // GLOBALS 53 | //------------------------------------------------------------------------------ 54 | // Initialize Adafruit stepper controller 55 | Adafruit_MotorShield AFMS0 = Adafruit_MotorShield(0x61); 56 | Adafruit_MotorShield AFMS1 = Adafruit_MotorShield(0x60); 57 | // Connect stepper motors with 400 steps per revolution (1.8 degree) 58 | // Create the motor shield object with the default I2C address 59 | Adafruit_StepperMotor *m[4]; 60 | 61 | 62 | Axis a[4]; // for line() 63 | Axis atemp; // for line() 64 | 65 | 66 | char serialBuffer[MAX_BUF]; // where we store the message until we get a ';' 67 | int sofar; // how much is in the buffer 68 | 69 | float px, py, pz, pe; // location 70 | 71 | // speeds 72 | float fr=0; // human version 73 | long step_delay; // machine version 74 | 75 | // settings 76 | char mode_abs=1; // absolute mode? 77 | 78 | long line_number=0; 79 | 80 | //------------------------------------------------------------------------------ 81 | // METHODS 82 | //------------------------------------------------------------------------------ 83 | 84 | 85 | /** 86 | * delay for the appropriate number of microseconds 87 | * @input ms how many milliseconds to wait 88 | */ 89 | void pause(long ms) { 90 | delay(ms/1000); 91 | delayMicroseconds(ms%1000); // delayMicroseconds doesn't work for values > ~16k. 92 | } 93 | 94 | 95 | /** 96 | * Set the feedrate (speed motors will move) 97 | * @input nfr the new speed in steps/second 98 | */ 99 | void feedrate(float nfr) { 100 | if(fr==nfr) return; // same as last time? Quit now. 101 | 102 | if(nfr>MAX_FEEDRATE || nfr onestep(direction>0?FORWARD:BACKWARD,SINGLE); 140 | } 141 | 142 | 143 | void release() { 144 | int i; 145 | for(i=0; i<4; ++i) { 146 | m[i]->release(); 147 | } 148 | } 149 | 150 | 151 | /** 152 | * Uses bresenham's line algorithm to move both motors 153 | * @input newx the destination x position 154 | * @input newy the destination y position 155 | **/ 156 | void line(float newx,float newy,float newz,float newe) { 157 | a[0].delta = newx-px; 158 | a[1].delta = newy-py; 159 | a[2].delta = newz-pz; 160 | a[3].delta = newe-pe; 161 | 162 | long i,j,maxsteps=0; 163 | 164 | for(i=0; i 0 ? 1:-1; 167 | if( maxsteps < a[i].absdelta ) maxsteps = a[i].absdelta; 168 | } 169 | 170 | for(i=0; i")); 176 | #endif 177 | 178 | for(i=0; i= maxsteps) { 182 | a[j].over -= maxsteps; 183 | onestep(j,a[j].dir); 184 | } 185 | } 186 | pause(step_delay); 187 | } 188 | 189 | #ifdef VERBOSE 190 | Serial.println(F("< Done.")); 191 | #endif 192 | position(newx,newy,newz,newe); 193 | } 194 | 195 | 196 | // returns angle of dy/dx as a value from 0...2PI 197 | static float atan3(float dy,float dx) { 198 | float a=atan2(dy,dx); 199 | if(a<0) a=(PI*2.0)+a; 200 | return a; 201 | } 202 | 203 | 204 | // This method assumes the limits have already been checked. 205 | // This method assumes the start and end radius match. 206 | // This method assumes arcs are not >180 degrees (PI radians) 207 | // cx/cy - center of circle 208 | // x/y - end position 209 | // dir - ARC_CW or ARC_CCW to control direction of arc 210 | static void arc(float cx,float cy,float x,float y,float dir) { 211 | // get radius 212 | float dx = px - cx; 213 | float dy = py - cy; 214 | float radius=sqrt(dx*dx+dy*dy); 215 | 216 | // find angle of arc (sweep) 217 | float angle1=atan3(dy,dx); 218 | float angle2=atan3(y-cy,x-cx); 219 | float theta=angle2-angle1; 220 | 221 | if(dir>0 && theta<0) angle2+=2*PI; 222 | else if(dir<0 && theta>0) angle1+=2*PI; 223 | 224 | theta=angle2-angle1; 225 | 226 | // get length of arc 227 | // float circ=PI*2.0*radius; 228 | // float len=theta*circ/(PI*2.0); 229 | // simplifies to 230 | float len = abs(theta) * radius; 231 | 232 | int i, segments = ceil( len * MM_PER_SEGMENT ); 233 | 234 | float nx, ny, angle3, scale; 235 | 236 | for(i=0;i 1 && (*ptr) && (long)ptr < (long)serialBuffer+sofar) { // walk to the end 260 | if(*ptr==code) { // if you find code on your walk, 261 | return atof(ptr+1); // convert the digits that follow into a float and return it 262 | } 263 | ptr=strchr(ptr,' ')+1; // take a step from here to the letter after the next space 264 | } 265 | return val; // end reached, nothing found, return default val. 266 | } 267 | 268 | 269 | /** 270 | * write a string followed by a float to the serial line. Convenient for debugging. 271 | * @input code the string. 272 | * @input val the float. 273 | */ 274 | void output(char *code, float val) { 275 | Serial.print(code); 276 | Serial.println(val); 277 | } 278 | 279 | 280 | /** 281 | * print the current position, feedrate, and absolute mode. 282 | */ 283 | void where() { 284 | output("X",px); 285 | output("Y",py); 286 | output("Z",pz); 287 | output("E",pe); 288 | output("F",fr); 289 | Serial.println(mode_abs?"ABS":"REL"); 290 | } 291 | 292 | 293 | /** 294 | * display helpful information 295 | */ 296 | void help() { 297 | Serial.print(F("GcodeCNCDemo4AxisV2 ")); 298 | Serial.println(VERSION); 299 | Serial.println(F("Commands:")); 300 | Serial.println(F("G00 [X(steps)] [Y(steps)] [Z(steps)] [E(steps)] [F(feedrate)]; - line")); 301 | Serial.println(F("G01 [X(steps)] [Y(steps)] [Z(steps)] [E(steps)] [F(feedrate)]; - line")); 302 | Serial.println(F("G02 [X(steps)] [Y(steps)] [I(steps)] [J(steps)] [F(feedrate)]; - clockwise arc")); 303 | Serial.println(F("G03 [X(steps)] [Y(steps)] [I(steps)] [J(steps)] [F(feedrate)]; - counter-clockwise arc")); 304 | Serial.println(F("G04 P[seconds]; - delay")); 305 | Serial.println(F("G90; - absolute mode")); 306 | Serial.println(F("G91; - relative mode")); 307 | Serial.println(F("G92 [X(steps)] [Y(steps)] [Z(steps)] [E(steps)]; - change logical position")); 308 | Serial.println(F("M18; - disable motors")); 309 | Serial.println(F("M100; - this help message")); 310 | Serial.println(F("M114; - report position and feedrate")); 311 | Serial.println(F("All commands must end with a newline.")); 312 | } 313 | 314 | 315 | /** 316 | * Read the input buffer and find any recognized commands. One G or M command per line. 317 | */ 318 | void processCommand() { 319 | // blank lines 320 | if(serialBuffer[0]==';') return; 321 | 322 | long cmd; 323 | 324 | // is there a line number? 325 | cmd=parseNumber('N',-1); 326 | if(cmd!=-1 && serialBuffer[0]=='N') { // line number must appear first on the line 327 | if(cmd != line_number) { 328 | // wrong line number error 329 | Serial.print(F("BADLINENUM ")); 330 | Serial.println(line_number); 331 | return; 332 | } 333 | 334 | // is there a checksum? 335 | if(strchr(serialBuffer,'*')!=0) { 336 | // yes. is it valid? 337 | char checksum=0; 338 | int c=0; 339 | while(serialBuffer[c]!='*') checksum ^= serialBuffer[c++]; 340 | c++; // skip * 341 | int against = strtod(serialBuffer+c,NULL); 342 | if(checksum != against) { 343 | Serial.print(F("BADCHECKSUM ")); 344 | Serial.println(line_number); 345 | return; 346 | } 347 | } else { 348 | Serial.print(F("NOCHECKSUM ")); 349 | Serial.println(line_number); 350 | return; 351 | } 352 | 353 | line_number++; 354 | } 355 | 356 | cmd = parseNumber('G',-1); 357 | switch(cmd) { 358 | case 0: 359 | case 1: { // line 360 | feedrate(parseNumber('F',fr)); 361 | line( parseNumber('X',(mode_abs?px:0)) + (mode_abs?0:px), 362 | parseNumber('Y',(mode_abs?py:0)) + (mode_abs?0:py), 363 | parseNumber('Z',(mode_abs?pz:0)) + (mode_abs?0:pz), 364 | parseNumber('E',(mode_abs?pe:0)) + (mode_abs?0:pe) ); 365 | break; 366 | } 367 | case 2: 368 | case 3: { // arc 369 | feedrate(parseNumber('F',fr)); 370 | arc(parseNumber('I',(mode_abs?px:0)) + (mode_abs?0:px), 371 | parseNumber('J',(mode_abs?py:0)) + (mode_abs?0:py), 372 | parseNumber('X',(mode_abs?px:0)) + (mode_abs?0:px), 373 | parseNumber('Y',(mode_abs?py:0)) + (mode_abs?0:py), 374 | (cmd==2) ? -1 : 1); 375 | break; 376 | } 377 | case 4: pause(parseNumber('P',0)*1000); break; // dwell 378 | case 90: mode_abs=1; break; // absolute mode 379 | case 91: mode_abs=0; break; // relative mode 380 | case 92: // set logical position 381 | position( parseNumber('X',0), 382 | parseNumber('Y',0), 383 | parseNumber('Z',0), 384 | parseNumber('E',0) ); 385 | break; 386 | default: break; 387 | } 388 | 389 | cmd = parseNumber('M',-1); 390 | switch(cmd) { 391 | case 18: // disable motors 392 | release(); 393 | break; 394 | case 100: help(); break; 395 | case 114: where(); break; 396 | default: break; 397 | } 398 | } 399 | 400 | 401 | /** 402 | * prepares the input buffer to receive a new message and tells the serial connected device it is ready for more. 403 | */ 404 | void ready() { 405 | sofar=0; // clear input buffer 406 | Serial.print(F(">")); // signal ready to receive input 407 | } 408 | 409 | 410 | /** 411 | * First thing this machine does on startup. Runs only once. 412 | */ 413 | void setup() { 414 | Serial.begin(BAUD); // open coms 415 | 416 | AFMS0.begin(); // Start the shieldS 417 | AFMS1.begin(); 418 | 419 | m[0] = AFMS0.getStepper(STEPS_PER_TURN, 1); 420 | m[1] = AFMS0.getStepper(STEPS_PER_TURN, 2); 421 | m[2] = AFMS1.getStepper(STEPS_PER_TURN, 1); 422 | m[3] = AFMS1.getStepper(STEPS_PER_TURN, 2); 423 | 424 | help(); // say hello 425 | position(0,0,0,0); // set staring position 426 | feedrate(200); // set default speed 427 | ready(); 428 | } 429 | 430 | 431 | /** 432 | * After setup() this machine will repeat loop() forever. 433 | */ 434 | void loop() { 435 | // listen for serial commands 436 | while(Serial.available() > 0) { // if something is available 437 | char c=Serial.read(); // get it 438 | Serial.print(c); // repeat it back so I know you got the message 439 | if(sofar. 466 | */ 467 | -------------------------------------------------------------------------------- /GcodeCNCDemo6AxisRumba/GcodeCNCDemo6AxisRumba.ino: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 6 Axis CNC Demo Rumba - supports raprapdiscount RUMBA controller 3 | // dan@marginallyclever.com 2013-10-28 4 | // RUMBA should be treated like a MEGA 2560 Arduino. 5 | //------------------------------------------------------------------------------ 6 | // Copyright at end of file. 7 | // please see http://www.github.com/MarginallyClever/GcodeCNCDemo for more information. 8 | 9 | 10 | //------------------------------------------------------------------------------ 11 | // CONSTANTS 12 | //------------------------------------------------------------------------------ 13 | //#define VERBOSE (1) // add to get a lot more serial output. 14 | 15 | #define VERSION (2) // firmware version 16 | #define BAUD (57600) // How fast is the Arduino talking? 17 | #define MAX_BUF (64) // What is the longest message Arduino can store? 18 | #define STEPS_PER_TURN (400) // depends on your stepper motor. most are 200. 19 | #define MAX_FEEDRATE (1000000.0) 20 | #define MIN_FEEDRATE (0.01) 21 | #define NUM_AXIES (6) 22 | 23 | // for arc directions 24 | #define ARC_CW (1) 25 | #define ARC_CCW (-1) 26 | // Arcs are split into many line segments. How long are the segments? 27 | #define MM_PER_SEGMENT (10) 28 | 29 | 30 | //------------------------------------------------------------------------------ 31 | // STRUCTS 32 | //------------------------------------------------------------------------------ 33 | // for line() 34 | typedef struct { 35 | long delta; // number of steps to move 36 | long absdelta; 37 | long over; // for dx/dy bresenham calculations 38 | } Axis; 39 | 40 | 41 | typedef struct { 42 | int step_pin; 43 | int dir_pin; 44 | int enable_pin; 45 | int limit_switch_pin; 46 | } Motor; 47 | 48 | 49 | //------------------------------------------------------------------------------ 50 | // GLOBALS 51 | //------------------------------------------------------------------------------ 52 | Axis a[NUM_AXIES]; // for line() 53 | Axis atemp; // for line() 54 | Motor motors[NUM_AXIES]; 55 | 56 | char serialBuffer[MAX_BUF]; // where we store the message until we get a ';' 57 | int sofar; // how much is in the buffer 58 | 59 | // speeds 60 | float fr=0; // human version 61 | long step_delay; // machine version 62 | 63 | float px,py,pz,pu,pv,pw; // position 64 | 65 | // settings 66 | char mode_abs=1; // absolute mode? 67 | 68 | long line_number=0; 69 | 70 | 71 | //------------------------------------------------------------------------------ 72 | // METHODS 73 | //------------------------------------------------------------------------------ 74 | 75 | 76 | /** 77 | * delay for the appropriate number of microseconds 78 | * @input ms how many milliseconds to wait 79 | */ 80 | void pause(long ms) { 81 | delay(ms/1000); 82 | delayMicroseconds(ms%1000); // delayMicroseconds doesn't work for values > ~16k. 83 | } 84 | 85 | 86 | /** 87 | * Set the feedrate (speed motors will move) 88 | * @input nfr the new speed in steps/second 89 | */ 90 | void feedrate(float nfr) { 91 | if(fr==nfr) return; // same as last time? quit now. 92 | 93 | if(nfr>MAX_FEEDRATE || nfr0?HIGH:LOW); 158 | } 159 | for(i=0;i maxsteps/2 ) 171 | steps_to_accel = maxsteps/2; 172 | 173 | long steps_to_decel = maxsteps - steps_to_accel; 174 | 175 | Serial.print("START "); 176 | Serial.println(dt); 177 | Serial.print("TOP "); 178 | Serial.println(step_delay); 179 | 180 | Serial.print("accel until "); 181 | Serial.println(steps_to_accel); 182 | Serial.print("decel after "); 183 | Serial.println(steps_to_decel); 184 | Serial.print("total "); 185 | Serial.println(maxsteps); 186 | #ifdef VERBOSE 187 | Serial.println(F("Start >")); 188 | #endif 189 | 190 | for( i=0; i= maxsteps) { 194 | a[j].over -= maxsteps; 195 | 196 | digitalWrite(motors[j].step_pin,HIGH); 197 | digitalWrite(motors[j].step_pin,LOW); 198 | } 199 | } 200 | 201 | if(i=steps_to_decel) { 205 | dt += accel; 206 | } 207 | delayMicroseconds(dt); 208 | } 209 | 210 | #ifdef VERBOSE 211 | Serial.println(F("< Done.")); 212 | #endif 213 | 214 | position(newx,newy,newz,newu,newv,neww); 215 | } 216 | 217 | 218 | // returns angle of dy/dx as a value from 0...2PI 219 | static float atan3(float dy,float dx) { 220 | float a=atan2(dy,dx); 221 | if(a<0) a=(PI*2.0)+a; 222 | return a; 223 | } 224 | 225 | 226 | // This method assumes the limits have already been checked. 227 | // This method assumes the start and end radius match. 228 | // This method assumes arcs are not >180 degrees (PI radians) 229 | // cx/cy - center of circle 230 | // x/y - end position 231 | // dir - ARC_CW or ARC_CCW to control direction of arc 232 | static void arc(float cx,float cy,float x,float y,float dir) { 233 | // get radius 234 | float dx = px - cx; 235 | float dy = py - cy; 236 | float radius=sqrt(dx*dx+dy*dy); 237 | 238 | // find angle of arc (sweep) 239 | float angle1=atan3(dy,dx); 240 | float angle2=atan3(y-cy,x-cx); 241 | float theta=angle2-angle1; 242 | 243 | if(dir>0 && theta<0) angle2+=2*PI; 244 | else if(dir<0 && theta>0) angle1+=2*PI; 245 | 246 | theta=angle2-angle1; 247 | 248 | // get length of arc 249 | // float circ=PI*2.0*radius; 250 | // float len=theta*circ/(PI*2.0); 251 | // simplifies to 252 | float len = abs(theta) * radius; 253 | 254 | int i, segments = ceil( len * MM_PER_SEGMENT ); 255 | 256 | float nx, ny, angle3, scale; 257 | 258 | for(i=0;i 1 && (*ptr) && (long)ptr < (long)serialBuffer+sofar) { // walk to the end 282 | if(*ptr==code) { // if you find code on your walk, 283 | return atof(ptr+1); // convert the digits that follow into a float and return it 284 | } 285 | ptr=strchr(ptr,' ')+1; // take a step from here to the letter after the next space 286 | } 287 | return val; // end reached, nothing found, return default val. 288 | } 289 | 290 | 291 | /** 292 | * write a string followed by a float to the serial line. Convenient for debugging. 293 | * @input code the string. 294 | * @input val the float. 295 | */ 296 | void output(char *code,float val) { 297 | Serial.print(code); 298 | Serial.println(val); 299 | } 300 | 301 | 302 | /** 303 | * print the current position, feedrate, and absolute mode. 304 | */ 305 | void where() { 306 | output("X",px); 307 | output("Y",py); 308 | output("Z",pz); 309 | output("U",pu); 310 | output("V",pv); 311 | output("W",pw); 312 | output("F",fr); 313 | Serial.println(mode_abs?"ABS":"REL"); 314 | } 315 | 316 | 317 | /** 318 | * display helpful information 319 | */ 320 | void help() { 321 | Serial.print(F("GcodeCNCDemo6AxisV2 ")); 322 | Serial.println(VERSION); 323 | Serial.println(F("Commands:")); 324 | Serial.println(F("G00/G01 [X/Y/Z/U/V/W(steps)] [F(feedrate)]; - linear move")); 325 | Serial.println(F("G02 [X(steps)] [Y(steps)] [I(steps)] [J(steps)] [F(feedrate)]; - clockwise arc")); 326 | Serial.println(F("G03 [X(steps)] [Y(steps)] [I(steps)] [J(steps)] [F(feedrate)]; - counter-clockwise arc")); 327 | Serial.println(F("G04 P[seconds]; - delay")); 328 | Serial.println(F("G90; - absolute mode")); 329 | Serial.println(F("G91; - relative mode")); 330 | Serial.println(F("G92 [X/Y/Z/U/V/W(steps)]; - change logical position")); 331 | Serial.println(F("M18; - disable motors")); 332 | Serial.println(F("M100; - this help message")); 333 | Serial.println(F("M114; - report position and feedrate")); 334 | Serial.println(F("All commands must end with a newline.")); 335 | } 336 | 337 | 338 | /** 339 | * Read the input buffer and find any recognized commands. One G or M command per line. 340 | */ 341 | void processCommand() { 342 | int cmd = parseNumber('G',-1); 343 | switch(cmd) { 344 | case 0: 345 | case 1: { // line 346 | feedrate(parseNumber('F',fr)); 347 | line( parseNumber('X',(mode_abs?px:0)) + (mode_abs?0:px), 348 | parseNumber('Y',(mode_abs?py:0)) + (mode_abs?0:py), 349 | parseNumber('Z',(mode_abs?pz:0)) + (mode_abs?0:pz), 350 | parseNumber('U',(mode_abs?pu:0)) + (mode_abs?0:pu), 351 | parseNumber('V',(mode_abs?pv:0)) + (mode_abs?0:pv), 352 | parseNumber('W',(mode_abs?pw:0)) + (mode_abs?0:pw) ); 353 | break; 354 | } 355 | case 2: 356 | case 3: { // arc 357 | feedrate(parseNumber('F',fr)); 358 | arc(parseNumber('I',(mode_abs?px:0)) + (mode_abs?0:px), 359 | parseNumber('J',(mode_abs?py:0)) + (mode_abs?0:py), 360 | parseNumber('X',(mode_abs?px:0)) + (mode_abs?0:px), 361 | parseNumber('Y',(mode_abs?py:0)) + (mode_abs?0:py), 362 | (cmd==2) ? -1 : 1); 363 | break; 364 | } 365 | case 4: pause(parseNumber('P',0)*1000); break; // dwell 366 | case 90: mode_abs=1; break; // absolute mode 367 | case 91: mode_abs=0; break; // relative mode 368 | case 92: // set logical position 369 | position( parseNumber('X',0), 370 | parseNumber('Y',0), 371 | parseNumber('Z',0), 372 | parseNumber('U',0), 373 | parseNumber('V',0), 374 | parseNumber('W',0) ); 375 | break; 376 | default: break; 377 | } 378 | 379 | cmd = parseNumber('M',-1); 380 | switch(cmd) { 381 | case 17: motor_enable(); break; 382 | case 18: motor_disable(); break; 383 | case 100: help(); break; 384 | case 114: where(); break; 385 | default: break; 386 | } 387 | } 388 | 389 | 390 | /** 391 | * prepares the input buffer to receive a new message and tells the serial connected device it is ready for more. 392 | */ 393 | void ready() { 394 | sofar=0; // clear input buffer 395 | Serial.print(F(">")); // signal ready to receive input 396 | } 397 | 398 | 399 | /** 400 | * set up the pins for each motor 401 | */ 402 | void motor_setup() { 403 | motors[0].step_pin=17; 404 | motors[0].dir_pin=16; 405 | motors[0].enable_pin=48; 406 | motors[0].limit_switch_pin=37; 407 | 408 | motors[1].step_pin=54; 409 | motors[1].dir_pin=47; 410 | motors[1].enable_pin=55; 411 | motors[1].limit_switch_pin=36; 412 | 413 | motors[2].step_pin=57; 414 | motors[2].dir_pin=56; 415 | motors[2].enable_pin=62; 416 | motors[2].limit_switch_pin=35; 417 | 418 | motors[3].step_pin=23; 419 | motors[3].dir_pin=22; 420 | motors[3].enable_pin=27; 421 | motors[3].limit_switch_pin=34; 422 | 423 | motors[4].step_pin=26; 424 | motors[4].dir_pin=25; 425 | motors[4].enable_pin=24; 426 | motors[4].limit_switch_pin=33; 427 | 428 | motors[5].step_pin=29; 429 | motors[5].dir_pin=28; 430 | motors[5].enable_pin=39; 431 | motors[5].limit_switch_pin=32; 432 | 433 | int i; 434 | for(i=0;i 0) { // if something is available 481 | char c=Serial.read(); // get it 482 | Serial.print(c); // repeat it back so I know you got the message 483 | if(sofar. 510 | */ 511 | -------------------------------------------------------------------------------- /GcodeCNCDemo6AxisRumbaTimerInterrupt/GcodeCNCDemo6AxisRumbaTimerInterrupt.ino: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 6 Axis CNC Demo Rumba - supports raprapdiscount RUMBA controller 3 | // dan@marginallyclever.com 2013-10-28 4 | // RUMBA should be treated like a MEGA 2560 Arduino. 5 | //------------------------------------------------------------------------------ 6 | // Copyright at end of file. 7 | // please see http://www.github.com/MarginallyClever/GcodeCNCDemo for more information. 8 | 9 | 10 | //------------------------------------------------------------------------------ 11 | // CONSTANTS 12 | //------------------------------------------------------------------------------ 13 | //#define VERBOSE (1) // add to get a lot more serial output. 14 | 15 | #define VERSION (2) // firmware version 16 | 17 | #define BAUD (57600) // How fast is the Arduino talking? 18 | #define MAX_BUF (64) // What is the longest message Arduino can store? 19 | 20 | #define STEPS_PER_TURN (3200) // depends on your stepper motor. most are 200. 21 | #define MAX_FEEDRATE (200) 22 | #define MIN_FEEDRATE (0.01) 23 | 24 | #define NUM_AXIES (6) 25 | 26 | #define CLOCK_FREQ (16000000L) 27 | #define MAX_COUNTER (65536L) 28 | #define MAX_SEGMENTS (32) 29 | 30 | 31 | // for arc directions 32 | #define ARC_CW (1) 33 | #define ARC_CCW (-1) 34 | // Arcs are split into many line segments. How long are the segments? 35 | #define MM_PER_SEGMENT (10) 36 | 37 | 38 | 39 | // RUMBA pins 40 | #define MOTOR_0_STEP_PIN (17) 41 | #define MOTOR_0_DIR_PIN (16) 42 | #define MOTOR_0_ENABLE_PIN (48) 43 | #define MOTOR_0_LIMIT_SWITCH_PIN (37) 44 | 45 | #define MOTOR_1_STEP_PIN (54) 46 | #define MOTOR_1_DIR_PIN (47) 47 | #define MOTOR_1_ENABLE_PIN (55) 48 | #define MOTOR_1_LIMIT_SWITCH_PIN (36) 49 | 50 | #define MOTOR_2_STEP_PIN (57) 51 | #define MOTOR_2_DIR_PIN (56) 52 | #define MOTOR_2_ENABLE_PIN (62) 53 | #define MOTOR_2_LIMIT_SWITCH_PIN (35) 54 | 55 | #define MOTOR_3_STEP_PIN (23) 56 | #define MOTOR_3_DIR_PIN (22) 57 | #define MOTOR_3_ENABLE_PIN (27) 58 | #define MOTOR_3_LIMIT_SWITCH_PIN (34) 59 | 60 | #define MOTOR_4_STEP_PIN (26) 61 | #define MOTOR_4_DIR_PIN (25) 62 | #define MOTOR_4_ENABLE_PIN (24) 63 | #define MOTOR_4_LIMIT_SWITCH_PIN (33) 64 | 65 | #define MOTOR_5_STEP_PIN (29) 66 | #define MOTOR_5_DIR_PIN (28) 67 | #define MOTOR_5_ENABLE_PIN (39) 68 | #define MOTOR_5_LIMIT_SWITCH_PIN (32) 69 | 70 | 71 | 72 | //------------------------------------------------------------------------------ 73 | // STRUCTS 74 | //------------------------------------------------------------------------------ 75 | // for line() 76 | typedef struct { 77 | long step_count; 78 | long delta; // number of steps to move 79 | long absdelta; 80 | long over; // for dx/dy bresenham calculations 81 | int dir; 82 | } Axis; 83 | 84 | 85 | typedef struct { 86 | int step_pin; 87 | int dir_pin; 88 | int enable_pin; 89 | int limit_switch_pin; 90 | } Motor; 91 | 92 | 93 | typedef struct { 94 | Axis a[NUM_AXIES]; 95 | int steps; 96 | int steps_left; 97 | long feed_rate; 98 | } Segment; 99 | 100 | 101 | //------------------------------------------------------------------------------ 102 | // GLOBALS 103 | //------------------------------------------------------------------------------ 104 | Axis a[NUM_AXIES]; // for line() 105 | Axis atemp; // for line() 106 | Motor motors[NUM_AXIES]; 107 | 108 | Segment line_segments[MAX_SEGMENTS]; 109 | volatile int current_segment; 110 | volatile int last_segment; 111 | unsigned int step_loops; 112 | 113 | char serialBuffer[MAX_BUF]; // where we store the message until we get a ';' 114 | int sofar; // how much is in the buffer 115 | 116 | // speeds 117 | float feed_rate=0; // human version 118 | 119 | float px,py,pz,pu,pv,pw; // position 120 | 121 | // settings 122 | char mode_abs=1; // absolute mode? 123 | 124 | long line_number=0; 125 | 126 | 127 | //------------------------------------------------------------------------------ 128 | // METHODS 129 | //------------------------------------------------------------------------------ 130 | 131 | 132 | /** 133 | * delay for the appropriate number of microseconds 134 | * @input ms how many milliseconds to wait 135 | */ 136 | void pause(long ms) { 137 | delay(ms/1000); 138 | delayMicroseconds(ms%1000); // delayMicroseconds doesn't work for values > ~16k. 139 | } 140 | 141 | 142 | /** 143 | * Set the feedrate (speed motors will move) 144 | * @input nfr the new speed in steps/second 145 | */ 146 | float feedrate(float nfr) { 147 | if(feed_rate==nfr) return nfr; // same as last time? quit now. 148 | 149 | if(nfr>MAX_FEEDRATE) { 150 | Serial.print(F("Feedrate set to maximum (")); 151 | Serial.print(MAX_FEEDRATE); 152 | Serial.println(F("steps/s)")); 153 | nfr=MAX_FEEDRATE; 154 | } 155 | if(nfr20000) { 203 | step_loops=4; 204 | desired_freq_hz>>=2; 205 | } else if(desired_freq_hz>10000) { 206 | step_loops=2; 207 | desired_freq_hz>>=1; 208 | } else { 209 | step_loops=1; 210 | } 211 | 212 | // CPU frequency 16Mhz for Arduino 213 | // maximum timer counter value (256 for 8bit, 65536 for 16bit timer) 214 | int prescaler_index=-1; 215 | int prescalers[] = {1,8,64,256,1024}; 216 | long counter_value; 217 | do { 218 | ++prescaler_index; 219 | // Divide CPU frequency through the choosen prescaler (16000000 / 256 = 62500) 220 | counter_value = CLOCK_FREQ / prescalers[prescaler_index]; 221 | // Divide result through the desired frequency (62500 / 2Hz = 31250) 222 | counter_value /= desired_freq_hz; 223 | // Verify counter_value < maximum timer. if fail, choose bigger prescaler. 224 | } while(counter_value > MAX_COUNTER && prescaler_index<4); 225 | 226 | if( prescaler_index>=5 ) { 227 | Serial.println(F("Timer could not be set: Desired frequency out of bounds.")); 228 | return; 229 | } 230 | 231 | #ifdef VERBOSE 232 | Serial.print(F("counter_value =")); Serial.print(counter_value); 233 | Serial.print(F(" prescaler_index=")); Serial.print(prescaler_index); 234 | Serial.print(F(" = ")); Serial.print(((prescaler_index&0x1) )); 235 | Serial.print(F("/")); Serial.print(((prescaler_index&0x2)>>1)); 236 | Serial.print(F("/")); Serial.println(((prescaler_index&0x4)>>2)); 237 | #endif 238 | 239 | // disable global interrupts 240 | noInterrupts(); 241 | 242 | // set entire TCCR1A register to 0 243 | TCCR1A = 0; 244 | // set entire TCCR1B register to 0 245 | TCCR1B = 0; 246 | // set the overflow clock to 0 247 | TCNT1 = 0; 248 | // set compare match register to desired timer count 249 | OCR1A = counter_value; 250 | // turn on CTC mode 251 | TCCR1B |= (1 << WGM12); 252 | // Set CS10, CS11, and CS12 bits for prescaler 253 | TCCR1B |= ( (( prescaler_index&0x1 ) ) << CS10); 254 | TCCR1B |= ( (( prescaler_index&0x2 )>>1) << CS11); 255 | TCCR1B |= ( (( prescaler_index&0x4 )>>2) << CS12); 256 | // enable timer compare interrupt 257 | TIMSK1 |= (1 << OCIE1A); 258 | 259 | interrupts(); // enable global interrupts 260 | } 261 | 262 | 263 | /** 264 | * Supports movement with both styles of Motor Shield 265 | * @input newx the destination x position 266 | * @input newy the destination y position 267 | **/ 268 | void onestep(int motor) { 269 | #ifdef VERBOSE 270 | char *letter="XYZUVW"; 271 | Serial.print(letter[motor]); 272 | #endif 273 | 274 | digitalWrite(motors[motor].step_pin,HIGH); 275 | digitalWrite(motors[motor].step_pin,LOW); 276 | } 277 | 278 | 279 | /** 280 | * Process all line segments in the ring buffer. Uses bresenham's line algorithm to move all motors. 281 | */ 282 | ISR(TIMER1_COMPA_vect) { 283 | // segment buffer empty? do nothing 284 | if( current_segment == last_segment ) return; 285 | 286 | // Is this segment done? 287 | if( line_segments[current_segment].steps_left <= 0 ) { 288 | // Move on to next segment without wasting an interrupt tick. 289 | current_segment = get_next_segment(current_segment); 290 | if( current_segment == last_segment ) return; 291 | } 292 | 293 | int j; 294 | Segment &seg = line_segments[current_segment]; 295 | // is this a fresh new segment? 296 | if( seg.steps == seg.steps_left ) { 297 | // set the direction pins 298 | for(j=0;j= seg.steps) { 318 | digitalWrite(motors[j].step_pin,LOW); 319 | a.over -= seg.steps; 320 | digitalWrite(motors[j].step_pin,HIGH); 321 | } 322 | } 323 | } 324 | } 325 | 326 | 327 | /** 328 | * Uses bresenham's line algorithm to move both motors 329 | **/ 330 | void line(int n0,int n1,int n2,int n3,int n4,int n5,float new_feed_rate) { 331 | int next_segment = get_next_segment(last_segment); 332 | while( next_segment == current_segment ) { 333 | // the buffer is full, we are way ahead of the motion system 334 | delay(1); 335 | } 336 | 337 | Segment &new_seg = line_segments[last_segment]; 338 | new_seg.a[0].step_count = n0; 339 | new_seg.a[1].step_count = n1; 340 | new_seg.a[2].step_count = n2; 341 | new_seg.a[3].step_count = n3; 342 | new_seg.a[4].step_count = n4; 343 | new_seg.a[5].step_count = n5; 344 | 345 | int i; 346 | 347 | Segment &old_seg = line_segments[get_prev_segment(last_segment)]; 348 | new_seg.a[0].delta = n0 - old_seg.a[0].step_count; 349 | new_seg.a[1].delta = n1 - old_seg.a[1].step_count; 350 | new_seg.a[2].delta = n2 - old_seg.a[2].step_count; 351 | new_seg.a[3].delta = n3 - old_seg.a[3].step_count; 352 | new_seg.a[4].delta = n4 - old_seg.a[4].step_count; 353 | new_seg.a[5].delta = n5 - old_seg.a[5].step_count; 354 | 355 | new_seg.steps=0; 356 | new_seg.feed_rate=new_feed_rate; 357 | 358 | for(i=0;i 0 ? LOW:HIGH); 361 | new_seg.a[i].absdelta = abs(new_seg.a[i].delta); 362 | if( new_seg.steps < new_seg.a[i].absdelta ) { 363 | new_seg.steps = new_seg.a[i].absdelta; 364 | } 365 | } 366 | 367 | if( new_seg.steps==0 ) return; 368 | 369 | new_seg.steps_left = new_seg.steps; 370 | 371 | if( current_segment==last_segment ) { 372 | timer_set_frequency(new_feed_rate); 373 | } 374 | 375 | #ifdef VERBOSE 376 | Serial.print(F("At ")); Serial.println(current_segment); 377 | Serial.print(F("Adding ")); Serial.println(last_segment); 378 | Serial.print(F("Steps= ")); Serial.println(new_seg.steps_left); 379 | #endif 380 | last_segment = next_segment; 381 | position(n0,n1,n2,n3,n4,n5); 382 | 383 | } 384 | 385 | 386 | // returns angle of dy/dx as a value from 0...2PI 387 | static float atan3(float dy,float dx) { 388 | float a=atan2(dy,dx); 389 | if(a<0) a=(PI*2.0)+a; 390 | return a; 391 | } 392 | 393 | 394 | // This method assumes the limits have already been checked. 395 | // This method assumes the start and end radius match. 396 | // This method assumes arcs are not >180 degrees (PI radians) 397 | // cx/cy - center of circle 398 | // x/y - end position 399 | // dir - ARC_CW or ARC_CCW to control direction of arc 400 | // fr - feed rate 401 | static void arc(float cx,float cy,float x,float y,float dir,float fr) { 402 | // get radius 403 | float dx = px - cx; 404 | float dy = py - cy; 405 | float radius=sqrt(dx*dx+dy*dy); 406 | 407 | // find angle of arc (sweep) 408 | float angle1=atan3(dy,dx); 409 | float angle2=atan3(y-cy,x-cx); 410 | float theta=angle2-angle1; 411 | 412 | if(dir>0 && theta<0) angle2+=2*PI; 413 | else if(dir<0 && theta>0) angle1+=2*PI; 414 | 415 | theta=angle2-angle1; 416 | 417 | // get length of arc 418 | // float circ=PI*2.0*radius; 419 | // float len=theta*circ/(PI*2.0); 420 | // simplifies to 421 | float len = abs(theta) * radius; 422 | 423 | int i, segments = ceil( len * MM_PER_SEGMENT ); 424 | 425 | float nx, ny, angle3, scale; 426 | 427 | for(i=0;i 1 && (*ptr) && (long)ptr < (long)serialBuffer+sofar) { // walk to the end 451 | if(*ptr==code) { // if you find code on your walk, 452 | return atof(ptr+1); // convert the digits that follow into a float and return it 453 | } 454 | ptr=strchr(ptr,' ')+1; // take a step from here to the letter after the next space 455 | } 456 | return val; // end reached, nothing found, return default val. 457 | } 458 | 459 | 460 | /** 461 | * write a string followed by a float to the serial line. Convenient for debugging. 462 | * @input code the string. 463 | * @input val the float. 464 | */ 465 | void output(char *code,float val) { 466 | Serial.print(code); 467 | Serial.println(val); 468 | } 469 | 470 | 471 | /** 472 | * print the current position, feedrate, and absolute mode. 473 | */ 474 | void where() { 475 | output("X",px); 476 | output("Y",py); 477 | output("Z",pz); 478 | output("U",pu); 479 | output("V",pv); 480 | output("W",pw); 481 | output("F",feed_rate); 482 | Serial.println(mode_abs?"ABS":"REL"); 483 | } 484 | 485 | 486 | /** 487 | * display helpful information 488 | */ 489 | void help() { 490 | Serial.print(F("GcodeCNCDemo6AxisV2 ")); 491 | Serial.println(VERSION); 492 | Serial.println(F("Commands:")); 493 | Serial.println(F("G00/G01 [X/Y/Z/U/V/W(steps)] [F(feedrate)]; - linear move")); 494 | Serial.println(F("G02 [X(steps)] [Y(steps)] [I(steps)] [J(steps)] [F(feedrate)]; - clockwise arc")); 495 | Serial.println(F("G03 [X(steps)] [Y(steps)] [I(steps)] [J(steps)] [F(feedrate)]; - counter-clockwise arc")); 496 | Serial.println(F("G04 P[seconds]; - delay")); 497 | Serial.println(F("G90; - absolute mode")); 498 | Serial.println(F("G91; - relative mode")); 499 | Serial.println(F("G92 [X/Y/Z/U/V/W(steps)]; - change logical position")); 500 | Serial.println(F("M18; - disable motors")); 501 | Serial.println(F("M100; - this help message")); 502 | Serial.println(F("M114; - report position and feedrate")); 503 | Serial.println(F("All commands must end with a newline.")); 504 | } 505 | 506 | 507 | /** 508 | * Read the input buffer and find any recognized commands. One G or M command per line. 509 | */ 510 | void processCommand() { 511 | int cmd = parseNumber('G',-1); 512 | switch(cmd) { 513 | case 0: 514 | case 1: { // line 515 | feedrate(parseNumber('F',feed_rate)); 516 | line( parseNumber('X',(mode_abs?px:0)) + (mode_abs?0:px), 517 | parseNumber('Y',(mode_abs?py:0)) + (mode_abs?0:py), 518 | parseNumber('Z',(mode_abs?pz:0)) + (mode_abs?0:pz), 519 | parseNumber('U',(mode_abs?pu:0)) + (mode_abs?0:pu), 520 | parseNumber('V',(mode_abs?pv:0)) + (mode_abs?0:pv), 521 | parseNumber('W',(mode_abs?pw:0)) + (mode_abs?0:pw), 522 | feed_rate ); 523 | break; 524 | } 525 | case 2: 526 | case 3: { // arc 527 | feedrate(parseNumber('F',feed_rate)); 528 | arc(parseNumber('I',(mode_abs?px:0)) + (mode_abs?0:px), 529 | parseNumber('J',(mode_abs?py:0)) + (mode_abs?0:py), 530 | parseNumber('X',(mode_abs?px:0)) + (mode_abs?0:px), 531 | parseNumber('Y',(mode_abs?py:0)) + (mode_abs?0:py), 532 | (cmd==2) ? -1 : 1, 533 | feed_rate ); 534 | break; 535 | } 536 | case 4: pause(parseNumber('P',0)*1000); break; // dwell 537 | case 90: mode_abs=1; break; // absolute mode 538 | case 91: mode_abs=0; break; // relative mode 539 | case 92: // set logical position 540 | position( parseNumber('X',0), 541 | parseNumber('Y',0), 542 | parseNumber('Z',0), 543 | parseNumber('U',0), 544 | parseNumber('V',0), 545 | parseNumber('W',0) ); 546 | break; 547 | default: break; 548 | } 549 | 550 | cmd = parseNumber('M',-1); 551 | switch(cmd) { 552 | case 17: motor_enable(); break; 553 | case 18: motor_disable(); break; 554 | case 100: help(); break; 555 | case 114: where(); break; 556 | default: break; 557 | } 558 | } 559 | 560 | 561 | /** 562 | * prepares the input buffer to receive a new message and tells the serial connected device it is ready for more. 563 | */ 564 | void ready() { 565 | sofar=0; // clear input buffer 566 | Serial.print(F(">")); // signal ready to receive input 567 | } 568 | 569 | 570 | /** 571 | * set up the pins for each motor 572 | */ 573 | void motor_setup() { 574 | motors[0].step_pin = MOTOR_0_STEP_PIN; 575 | motors[0].dir_pin = MOTOR_0_DIR_PIN; 576 | motors[0].enable_pin = MOTOR_0_ENABLE_PIN; 577 | motors[0].limit_switch_pin = MOTOR_0_LIMIT_SWITCH_PIN; 578 | 579 | motors[1].step_pin = MOTOR_1_STEP_PIN; 580 | motors[1].dir_pin = MOTOR_1_DIR_PIN; 581 | motors[1].enable_pin = MOTOR_1_ENABLE_PIN; 582 | motors[1].limit_switch_pin = MOTOR_1_LIMIT_SWITCH_PIN; 583 | 584 | motors[2].step_pin = MOTOR_2_STEP_PIN; 585 | motors[2].dir_pin = MOTOR_2_DIR_PIN; 586 | motors[2].enable_pin = MOTOR_2_ENABLE_PIN; 587 | motors[2].limit_switch_pin = MOTOR_2_LIMIT_SWITCH_PIN; 588 | 589 | motors[3].step_pin = MOTOR_3_STEP_PIN; 590 | motors[3].dir_pin = MOTOR_3_DIR_PIN; 591 | motors[3].enable_pin = MOTOR_3_ENABLE_PIN; 592 | motors[3].limit_switch_pin = MOTOR_3_LIMIT_SWITCH_PIN; 593 | 594 | motors[4].step_pin = MOTOR_4_STEP_PIN; 595 | motors[4].dir_pin = MOTOR_4_DIR_PIN; 596 | motors[4].enable_pin = MOTOR_4_ENABLE_PIN; 597 | motors[4].limit_switch_pin = MOTOR_4_LIMIT_SWITCH_PIN; 598 | 599 | motors[5].step_pin = MOTOR_5_STEP_PIN; 600 | motors[5].dir_pin = MOTOR_5_DIR_PIN; 601 | motors[5].enable_pin = MOTOR_5_ENABLE_PIN; 602 | motors[5].limit_switch_pin = MOTOR_5_LIMIT_SWITCH_PIN; 603 | 604 | int i; 605 | for(i=0;i 0) { // if something is available 652 | char c=Serial.read(); // get it 653 | Serial.print(c); // repeat it back so I know you got the message 654 | if(sofar. 681 | */ 682 | --------------------------------------------------------------------------------