└── Arduino Uno └── ClearPathStepGen ├── ClearPathMotorSD.cpp ├── ClearPathMotorSD.h ├── ClearPathStepGen.cpp ├── ClearPathStepGen.h ├── Examples ├── MultiAxisDemo │ └── MultiAxisDemo.ino └── SingleAxisDemo │ └── SingleAxisDemo.ino ├── Keywords.txt └── ReadMe.txt /Arduino Uno/ClearPathStepGen/ClearPathMotorSD.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ClearPathMotorSD.h - Library for interfacing with Clearpath-SD motors using an Arduino- Version 1 3 | Teknic 2017 Brendan Flosenzier 4 | 5 | Copyright (c) 2017 Teknic Inc. This work is free to use, copy and distribute under the terms of the standard 6 | MIT permissive software license which can be found at https://opensource.org/licenses/MIT 7 | 8 | This library is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 | */ 12 | 13 | /* 14 | 15 | A ClearPathMotorSD is activated by creating an instance of the ClearPathMotorSD class. 16 | 17 | There can several instances of ClearPathMotorSD however each must be attached to different pins. 18 | 19 | This class is used in conjuntion with the ClearPathStepGen class which manages and sends step pulses to each motor. 20 | 21 | Note: Each attached motor must have its direction/B pin connected to one of pins 8-13 on an arduino UNO (PORTB) 22 | in order to work with the ClearPathStepGen object. Other devices can be connected to pins 8-13 as well. 23 | If you are using another Arduino besides the UNO, the ClearPathStepGen must be modifyed to use a different port. 24 | 25 | The functions for a ClearPathMotorSD are: 26 | 27 | ClearPathMotorSD - default constructor for initializing the motor 28 | 29 | attach() - Attachs pins to this motor, and declares them as input/outputs 30 | 31 | stopMove() - Interupts the current move, the motor may abruptly stop 32 | 33 | move() - sets the maximum veloctiy 34 | 35 | disable() - disables the motor 36 | 37 | enable() - enables the motor 38 | 39 | getCommandedPosition() - Returns the absolute cmomanded position where the position on enable=0 40 | 41 | readHLFB() - Returns the value of the motor's HLFB Pin 42 | 43 | setMaxVel() - sets the maximum veloctiy 44 | 45 | setMaxAccel() - sets the acceleration 46 | 47 | commandDone() - returns wheter or not there is a valid current command 48 | 49 | */ 50 | #include "Arduino.h" 51 | #include "ClearPathMotorSD.h" 52 | 53 | 54 | /* 55 | This is an internal Function used by ClearPathStepGen to calculate how many pulses to send to each motor. 56 | It tracks the current command, as well as how many steps have been sent, and calculates how many steps 57 | to send in the next ISR. 58 | */ 59 | int ClearPathMotorSD::calcSteps() 60 | { 61 | _TX++;//increment time 62 | if(!Enabled) 63 | return 0; 64 | 65 | // Process current move state. 66 | switch(moveStateX){ 67 | case 3: // IdleState state, executed only once. 68 | 69 | if(CommandX == 0) //If no/finished command/, do nothing set everything to 0 70 | { 71 | MovePosnQx=0; 72 | VelRefQx=0; 73 | StepsSent=0; 74 | _TX=0; 75 | _TX1=0; 76 | _TX2=0; 77 | _TX3=0; 78 | _BurstX=0; 79 | } 80 | else 81 | { 82 | // Compute Move parameters 83 | TargetPosnQx = CommandX<>1); 85 | if(TargetPosnQx > 0) 86 | AccelRefQxS = AccLimitQx; 87 | else 88 | AccelRefQxS = -AccLimitQx; 89 | AccelRefQx = AccelRefQxS; 90 | // Do immediate move if half move length <= maximum acceleration. 91 | if(TriangleMovePeakQx <= AccLimitQx) { 92 | AccelRefQx = 0; 93 | VelRefQx = 0; 94 | MovePosnQx = TargetPosnQx; 95 | moveStateX = 3; //Set to Move Idle 96 | CommandX=0; //Zero command 97 | break; 98 | } 99 | // Otherwise, execute move and go to Phase1 100 | MovePosnQx = MovePosnQx + VelRefQx;// + (AccelRefQx>>1); 101 | VelRefQx = VelRefQx + AccelRefQx; 102 | moveStateX = 1; 103 | } 104 | break; 105 | 106 | case 1: //Phase 1 first half of move 107 | 108 | // Execute move 109 | MovePosnQx = MovePosnQx + VelRefQx + (AccelRefQx>>1); 110 | VelRefQx = VelRefQx + AccelRefQx; 111 | 112 | // Check position. 113 | if(abs(MovePosnQx) >= TriangleMovePeakQx) { 114 | // If half move reached, compute time parameters and go to PXhase2 115 | 116 | if(_flag) //This makes sure you go one step past half in order to make sure Phase 2 goes well 117 | { 118 | if(_TX1 == 0) { 119 | _TX1 = _TX; 120 | } 121 | if(_TX2 == 0) { 122 | _TX2 = _TX; 123 | } 124 | AccelRefQx = -AccelRefQx; //Set deccelleration 125 | _TX3 = (_TX2<<1) - _TX1; //compute time params 126 | _TAUX = _TX2<<1; 127 | moveStateX = 2; //Start Phase 2 128 | } 129 | _flag=true; 130 | 131 | } 132 | else { 133 | // Otherwise, check velocity. 134 | if(labs(VelRefQx) >= VelLimitQx) { 135 | // If maximum velocity reached, compute TX1 and set AX = 0, and VelRefQx=VelLimitQx. 136 | if(_TX1 == 0) { 137 | AccelRefQx = 0; 138 | _TX1 = _TX; 139 | if(VelRefQx > 0) 140 | VelRefQx=VelLimitQx; 141 | else 142 | VelRefQx=-VelLimitQx; 143 | } 144 | } 145 | } 146 | break; 147 | 148 | case 2: //Phase 2 2nd half of move 149 | // Execute move 150 | MovePosnQx = MovePosnQx + VelRefQx + (AccelRefQx>>1); 151 | VelRefQx = VelRefQx + AccelRefQx; 152 | 153 | // Check time. 154 | if(_TX >= _TX3) { 155 | // If beyond TX3, wait for done condition. 156 | AccelRefQx = -AccelRefQxS; 157 | if((_TX > _TAUX) || (labs(MovePosnQx) > labs(TargetPosnQx)) || (VelRefQx*AccelRefQx > 0)) { 158 | // If done, enforce final position. 159 | AccelRefQx = 0; 160 | VelRefQx = 0; 161 | MovePosnQx = TargetPosnQx; 162 | moveStateX = 3; 163 | CommandX=0; 164 | } 165 | } 166 | break; 167 | case 4: //Fast move case 168 | // Execute move 169 | TargetPosnQx = CommandX<50<>fractionalBits; 184 | // Update accumulated integer position 185 | StepsSent += (long)(_BurstX)<calcSteps(); 67 | } 68 | 69 | 70 | 71 | //loop through BurstSteps decrementing each value to 0 72 | do 73 | { 74 | 75 | _flag=false; 76 | 77 | _OutputBits = PORTB; //Read the port 78 | 79 | if(_BurstSteps[0] && _BurstSteps[0]--) //Assume at least one axis is active, and check/decrement BurstSteps 80 | { 81 | _flag=true; 82 | _OutputBits |= _pins[0]; //Activate the B input for motor 1 83 | } 84 | if(_pins[1] > 0 && _BurstSteps[1] && _BurstSteps[1]--) //Check if Axis is active, then check/decrement BurstSteps 85 | { 86 | _flag=true; 87 | _OutputBits |= _pins[1]; //Activate the B input for motor 2 88 | } 89 | if(_pins[2] > 0 && _BurstSteps[2] && _BurstSteps[2]--) //Check if Axis is active, then check/decrement BurstSteps 90 | { 91 | _flag=true; 92 | _OutputBits |= _pins[2]; //Activate the B input for motor 3 93 | } 94 | if(_pins[3] > 0 && _BurstSteps[3] && _BurstSteps[3]--) //Check if Axis is active, then check/decrement BurstSteps 95 | { 96 | _flag=true; 97 | _OutputBits |= _pins[3]; //Activate the B input for motor 4 98 | } 99 | if(_pins[4] > 0 && _BurstSteps[4] && _BurstSteps[4]--) //Check if Axis is active, then check/decrement BurstSteps 100 | { 101 | _flag=true; 102 | _OutputBits |= _pins[4]; //Activate the B input for motor 5 103 | } 104 | if(_pins[5] > 0 && _BurstSteps[5] && _BurstSteps[5]--) //Check if Axis is active, then check/decrement BurstSteps 105 | { 106 | _flag=true; 107 | _OutputBits |= _pins[5]; //Activate the B input for motor 6 108 | } 109 | PORTB = _OutputBits; //Write to the ports 110 | delayMicroseconds(2); //Short Delay 111 | _OutputBits &=63-_SUMPINS ; //Turn off all active pins 112 | PORTB = _OutputBits; //Write to the ports 113 | 114 | } while(_flag); 115 | 116 | //turn off debug pin 117 | //digitalWrite(2,LOW); 118 | //allow interupts 119 | sei(); 120 | 121 | } 122 | 123 | /* This is the minimum constructor for ClearPathStepGen it requires a pointer to one ClearPathMotorSD, or 124 | one ClearPathMotorSD motor. It requires a pointer because this class must use the functions of the 125 | same clearpath object used in the main routine. 126 | 127 | This function saves the clearpath pointer, and establishes the pins of said motor 128 | NOTE: the DirPins of the passed motor must be one of pins 8-13 129 | */ 130 | ClearPathStepGen::ClearPathStepGen(ClearPathMotorSD* motor1) 131 | { 132 | _SUMPINS=0; 133 | _flag=false; 134 | _numAxis=1; 135 | _motors[0]=motor1; 136 | if(_motors[0]->PinB-8 >= 0) 137 | _pins[0]=(1<<(_motors[0]->PinB-8)); 138 | _SUMPINS=_pins[0]; 139 | } 140 | 141 | /* This is a constructor for ClearPathStepGen, it requires 2 pointer to ClearPathMotorSD, or 142 | ClearPathMotorSD motors. It requires pointers because this class must use the functions of the 143 | same clearpath objects used in the main routine. 144 | 145 | This function saves the clearpath pointers, and establishes the pins of said motors 146 | NOTE: the DirPins of the passed motor must each be one different of pins 8-13 147 | */ 148 | ClearPathStepGen::ClearPathStepGen(ClearPathMotorSD* motor1, ClearPathMotorSD* motor2) 149 | { 150 | _SUMPINS=0; 151 | _flag=false; 152 | _numAxis=2; 153 | _motors[0]=motor1; 154 | _motors[1]=motor2; 155 | if(_motors[0]->PinB-8 >= 0) 156 | _pins[0]=(1<<(_motors[0]->PinB-8)); 157 | if(_motors[1]->PinB-8 >= 0) 158 | _pins[1]=(1<<(_motors[1]->PinB-8)); 159 | _SUMPINS=_pins[0]+_pins[1]; 160 | } 161 | 162 | /* This is a constructor for ClearPathStepGen, it requires 3 pointer to ClearPathMotorSD, or 163 | ClearPathMotorSD motors. It requires pointers because this class must use the functions of the 164 | same clearpath objects used in the main routine. 165 | 166 | This function saves the clearpath pointers, and establishes the pins of said motors 167 | NOTE: the DirPins of the passed motor must each be one different of pins 8-13 168 | */ 169 | ClearPathStepGen::ClearPathStepGen(ClearPathMotorSD* motor1, ClearPathMotorSD* motor2, ClearPathMotorSD* motor3) 170 | { 171 | _SUMPINS=0; 172 | _flag=false; 173 | _numAxis=3; 174 | _motors[0]=motor1; 175 | _motors[1]=motor2; 176 | _motors[2]=motor3; 177 | if(_motors[0]->PinB-8 >= 0) 178 | _pins[0]=(1<<(_motors[0]->PinB-8)); 179 | if(_motors[1]->PinB-8 >= 0) 180 | _pins[1]=(1<<(_motors[1]->PinB-8)); 181 | if(_motors[2]->PinB-8 >= 0) 182 | _pins[2]=(1<<(_motors[2]->PinB-8)); 183 | _SUMPINS=_pins[0]+_pins[1]+_pins[2]; 184 | 185 | } 186 | 187 | /* This is a constructor for ClearPathStepGen, it requires 4 pointer to ClearPathMotorSD, or 188 | ClearPathMotorSD motors. It requires pointers because this class must use the functions of the 189 | same clearpath objects used in the main routine. 190 | 191 | This function saves the clearpath pointers, and establishes the pins of said motors 192 | NOTE: the DirPins of the passed motor must each be one different of pins 8-13 193 | */ 194 | ClearPathStepGen::ClearPathStepGen(ClearPathMotorSD* motor1, ClearPathMotorSD* motor2, ClearPathMotorSD* motor3, ClearPathMotorSD* motor4) 195 | { 196 | _SUMPINS=0; 197 | _flag=false; 198 | _numAxis=4; 199 | _motors[0]=motor1; 200 | _motors[1]=motor2; 201 | _motors[2]=motor3; 202 | _motors[3]=motor4; 203 | if(_motors[0]->PinB-8 >= 0) 204 | _pins[0]=(1<<(_motors[0]->PinB-8)); 205 | if(_motors[1]->PinB-8 >= 0) 206 | _pins[1]=(1<<(_motors[1]->PinB-8)); 207 | if(_motors[2]->PinB-8 >= 0) 208 | _pins[2]=(1<<(_motors[2]->PinB-8)); 209 | if(_motors[3]->PinB-8 >= 0) 210 | _pins[3]=(1<<(_motors[3]->PinB-8)); 211 | _SUMPINS=_pins[0]+_pins[1]+_pins[2]+_pins[3]; 212 | 213 | } 214 | 215 | /* This is a constructor for ClearPathStepGen, it requires 5 pointer to ClearPathMotorSD, or 216 | ClearPathMotorSD motors. It requires pointers because this class must use the functions of the 217 | same clearpath objects used in the main routine. 218 | 219 | This function saves the clearpath pointers, and establishes the pins of said motors 220 | NOTE: the DirPins of the passed motor must each be one different of pins 8-13 221 | */ 222 | ClearPathStepGen::ClearPathStepGen(ClearPathMotorSD* motor1, ClearPathMotorSD* motor2, ClearPathMotorSD* motor3, ClearPathMotorSD* motor4, ClearPathMotorSD* motor5) 223 | { 224 | _SUMPINS=0; 225 | _flag=false; 226 | _numAxis=5; 227 | _motors[0]=motor1; 228 | _motors[1]=motor2; 229 | _motors[2]=motor3; 230 | _motors[3]=motor4; 231 | _motors[4]=motor5; 232 | if(_motors[0]->PinB-8 >= 0) 233 | _pins[0]=(1<<(_motors[0]->PinB-8)); 234 | if(_motors[1]->PinB-8 >= 0) 235 | _pins[1]=(1<<(_motors[1]->PinB-8)); 236 | if(_motors[2]->PinB-8 >= 0) 237 | _pins[2]=(1<<(_motors[2]->PinB-8)); 238 | if(_motors[3]->PinB-8 >= 0) 239 | _pins[3]=(1<<(_motors[3]->PinB-8)); 240 | if(_motors[4]->PinB-8 >= 0) 241 | _pins[4]=(1<<(_motors[4]->PinB-8)); 242 | _SUMPINS=_pins[0]+_pins[1]+_pins[2]+_pins[3]+_pins[4]; 243 | 244 | } 245 | 246 | /* This is a constructor for ClearPathStepGen, it requires 6 pointer to ClearPathMotorSD, or 247 | ClearPathMotorSD motors. It requires pointers because this class must use the functions of the 248 | same clearpath objects used in the main routine. 249 | 250 | This function saves the clearpath pointers, and establishes the pins of said motors 251 | NOTE: the DirPins of the passed motor must each be one different of pins 8-13 252 | */ 253 | ClearPathStepGen::ClearPathStepGen(ClearPathMotorSD* motor1, ClearPathMotorSD* motor2, ClearPathMotorSD* motor3, ClearPathMotorSD* motor4, ClearPathMotorSD* motor5, ClearPathMotorSD* motor6) 254 | { 255 | _SUMPINS=0; 256 | _flag=false; 257 | _numAxis=6; 258 | _motors[0]=motor1; 259 | _motors[1]=motor2; 260 | _motors[2]=motor3; 261 | _motors[3]=motor4; 262 | _motors[4]=motor5; 263 | _motors[5]=motor6; 264 | if(_motors[0]->PinB-8 >= 0) 265 | _pins[0]=(1<<(_motors[0]->PinB-8)); 266 | if(_motors[1]->PinB-8 >= 0) 267 | _pins[1]=(1<<(_motors[1]->PinB-8)); 268 | if(_motors[2]->PinB-8 >= 0) 269 | _pins[2]=(1<<(_motors[2]->PinB-8)); 270 | if(_motors[3]->PinB-8 >= 0) 271 | _pins[3]=(1<<(_motors[3]->PinB-8)); 272 | if(_motors[4]->PinB-8 >= 0) 273 | _pins[4]=(1<<(_motors[4]->PinB-8)); 274 | if(_motors[5]->PinB-8 >= 0) 275 | _pins[5]=(1<<(_motors[5]->PinB-8)); 276 | _SUMPINS=_pins[0]+_pins[1]+_pins[2]+_pins[3]+_pins[4]+_pins[5]; 277 | 278 | } 279 | 280 | /* 281 | This function sets up the ISR to run at 2kHz if it is passed the value of 249. 282 | It also, rechecks the direction pins of each connected motor 283 | */ 284 | void ClearPathStepGen::Start() 285 | { 286 | int time = 249; //Set Frequency 2kHz 287 | _SUMPINS=0; 288 | for( int i=0; i<_numAxis; i++) 289 | { 290 | if(_motors[i]->PinB-8 >= 0) 291 | _pins[i]=(1<<(_motors[i]->PinB-8)); 292 | _SUMPINS+=_pins[i]; 293 | } 294 | 295 | cli();//stop interrupts 296 | 297 | // set up Timer 1 298 | TCCR2A = 0;// set entire TCCR2A register to 0 299 | TCCR2B = 0;// same for TCCR2B 300 | TCNT2 = 0;//initialize counter value to 0 301 | 302 | //Set compare match register to time 303 | OCR2A = time;// time should be 249, 1-256 will produce different frequencies 304 | 305 | // turn on CTC mode 306 | TCCR2A |= (1 << WGM21); 307 | 308 | // Set CS21 bit for 8 prescaler 309 | TCCR2B = 0; 310 | TCCR2B |= (1 << CS01) | (1 << CS00); 311 | 312 | // enable timer compare interrupt 313 | TIMSK2=0; 314 | TIMSK2 |= (1 << OCIE2A); 315 | 316 | sei();//allow interrupts 317 | } 318 | 319 | /* 320 | This function disables the ISR so any motor connected will no longer output pulses 321 | The motors should remember what command they were on, but if a move was interuppted 322 | by this function, large accelerations/deccelerations may be experienced. 323 | */ 324 | void ClearPathStepGen::Stop() 325 | { 326 | cli();//stop interrupts 327 | // 328 | // set up Timer 1 329 | TCCR2A = 0;// set entire TCCR2A register to 0 330 | TCCR2B = 0;// same for TCCR2B 331 | TCNT2 = 0;//initialize counter value to 0 332 | 333 | sei();//allow interrupts 334 | } 335 | 336 | // This is a debugging function 337 | int ClearPathStepGen::getsum() 338 | { 339 | return _motors[0]->calcSteps(); 340 | } 341 | 342 | -------------------------------------------------------------------------------- /Arduino Uno/ClearPathStepGen/ClearPathStepGen.h: -------------------------------------------------------------------------------- 1 | /* 2 | ClearPathStepGen.h - Interrupt driven library for controlling Clearpath motors using an Arduino- Version 1 3 | Teknic 2017 Brendan Flosenzier 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it. 7 | 8 | This library is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 | */ 12 | 13 | /* 14 | 15 | A ClearPathStepGen is activated by creating an instance of the ClearPathStepGen class, and passing the constructor references to the motors it will control. 16 | The motors are pulsed in the background according to move information stored within each motor. 17 | Only motors of type; ClearPathMotorSD may be used. 18 | 19 | There can only be one instance of Step Controller at any time. 20 | 21 | This class uses Timer2, so other functions and classes which use timer 2 will not work correctly ie: tone(), MsTimer2() etc. 22 | 23 | The ISR is set to 2KHz, nominally 24 | 25 | Note: Each attached motor must have its direction/B pin connected to one of pins 8-13 26 | 27 | other devices can be connected to pins 8-13 as well 28 | 29 | 30 | Start(time) - gets Direction pins for all connected motors (make sure all motors have been attached before this is called 31 | Configures the ISR to run at 2kHz 32 | Stop() - disables the ISR in this class 33 | 34 | */ 35 | #ifndef ClearPathStepGen_h 36 | #define ClearPathStepGen_h 37 | 38 | #include "Arduino.h" 39 | #include "ClearPathMotorSD.h" 40 | 41 | class ClearPathStepGen 42 | { 43 | public: 44 | ClearPathStepGen(ClearPathMotorSD* motor1); 45 | ClearPathStepGen(ClearPathMotorSD* motor1, ClearPathMotorSD* motor2); 46 | ClearPathStepGen(ClearPathMotorSD* motor1, ClearPathMotorSD* motor2, ClearPathMotorSD* motor3); 47 | ClearPathStepGen(ClearPathMotorSD* motor1, ClearPathMotorSD* motor2, ClearPathMotorSD* motor3, ClearPathMotorSD* motor4); 48 | ClearPathStepGen(ClearPathMotorSD* motor1, ClearPathMotorSD* motor2, ClearPathMotorSD* motor3, ClearPathMotorSD* motor4, ClearPathMotorSD* motor5); 49 | ClearPathStepGen(ClearPathMotorSD* motor1, ClearPathMotorSD* motor2, ClearPathMotorSD* motor3, ClearPathMotorSD* motor4, ClearPathMotorSD* motor5, ClearPathMotorSD* motor6); 50 | void Start(); 51 | void Stop(); 52 | int getsum(); 53 | 54 | 55 | }; 56 | #endif 57 | -------------------------------------------------------------------------------- /Arduino Uno/ClearPathStepGen/Examples/MultiAxisDemo/MultiAxisDemo.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Multi Axis Axample 3 | Runs 3 a Teknic ClearPath SDSK or SDHP motors 4 | 5 | the motors cycle forward taking turns starting with X, then both X and Y, then X, Y, and Z 6 | 7 | 8 | Copyright (c) 2017 Teknic Inc. This work is free to use, copy and distribute under the terms of the standard 9 | MIT permissive software license which can be found at https://opensource.org/licenses/MIT 10 | */ 11 | 12 | 13 | 14 | //Import Required libraries 15 | #include 16 | #include 17 | 18 | // initialize a ClearPathMotorSD Motors 19 | ClearPathMotorSD X,Y,Z; 20 | 21 | //initialize the controller and pass the references to the motors we are controlling 22 | ClearPathStepGen machine(&X,&Y,&Z); 23 | 24 | // the setup routine runs once when you press reset: 25 | void setup() 26 | { 27 | 28 | //Begin Serial Communication // NOTE: WHEN GOING FAST, communication may lag 29 | Serial.begin(9600); 30 | 31 | //Setup pins, In this example all motors share the same enable signal 32 | X.attach(8,9,6,4); //Direction/A is pin 8, Step/B is pin 9, Enable is pin 6, HLFB is pin 4 33 | Y.attach(10,11,6,5); //Direction/A is pin 10, Step/B is pin 11, Enable is pin 6, HLFB is pin 5 34 | Z.attach(12,13,6,7); //Direction/A is pin 12, Step/B is pin 13, Enable is pin 6, HLFB is pin 7 35 | 36 | //Set velocity and Acceleration in steps/sec, and steps/sec/sec 37 | X.setMaxVel(100000); 38 | X.setMaxAccel(200000); 39 | Y.setMaxVel(10000); 40 | Y.setMaxAccel(20000); 41 | Z.setMaxVel(100000); 42 | Z.setMaxAccel(4000); 43 | 44 | // Enable motors, reset each motors position to 0 45 | X.enable(); 46 | Y.enable(); 47 | Z.enable(); 48 | 49 | delay(100); 50 | 51 | // Set up the ISR to constantly update motor position. 52 | machine.Start(); 53 | 54 | 55 | } 56 | 57 | // the loop routine runs over and over again forever: 58 | void loop() 59 | { 60 | // Move the X motor forward 50,000 counts 61 | X.move(50000); 62 | Serial.println("X Motor Move"); 63 | 64 | // wait until the command is finished and the motor's HLFB asserts 65 | while(!X.commandDone()||!X.readHLFB()) //just use command done if not using motor feedback 66 | { } 67 | 68 | // Move the Y motor forward 100,000 counts 69 | Y.move(100000); 70 | Serial.println("Y Motor Move"); 71 | // Move the X motor back 50,000 counts 72 | X.move(50000); 73 | Serial.println("X Motor Move"); 74 | 75 | // wait until the command is finished and both motor's HLFB asserts 76 | while(!Y.commandDone()||!Y.readHLFB()||!X.commandDone()||!X.readHLFB()) 77 | { } 78 | 79 | // Move the Y motor back 50,000 counts 80 | Y.move(-50000); 81 | Serial.println("Y Motor Move"); 82 | // Move the X motor back 50,000 counts 83 | X.move(-50000); 84 | Serial.println("X Motor Move"); 85 | // Move the Z motor forward 100,000 counts 86 | Z.move(100000); 87 | Serial.println("Z Motor Move"); 88 | 89 | // wait until the command is finished and The motor's HLFB asserts 90 | while(!Z.commandDone()||!Z.readHLFB()||!Y.commandDone()||!Y.readHLFB()||!X.commandDone()||!X.readHLFB()) 91 | { } 92 | 93 | 94 | // Move the Y motor back 50,000 counts 95 | Y.move(-50000); 96 | Serial.println("Y Motor Move"); 97 | // Move the X motor back 50,000 counts 98 | X.move(-50000); 99 | Serial.println("X Motor Move"); 100 | // Move the Z motor forward 100,000 counts 101 | Z.move(-100000); 102 | Serial.println("Z Motor Move"); 103 | 104 | // wait until the command is finished and The motor's HLFB asserts 105 | while(!Z.commandDone()||!Z.readHLFB()||!Y.commandDone()||!Y.readHLFB()||!X.commandDone()||!X.readHLFB()) 106 | { } 107 | 108 | 109 | 110 | } 111 | -------------------------------------------------------------------------------- /Arduino Uno/ClearPathStepGen/Examples/SingleAxisDemo/SingleAxisDemo.ino: -------------------------------------------------------------------------------- 1 | /* 2 | SingleAxisDemo 3 | Runs a Teknic ClearPath SDSK or SDHP motor, back and forth 4 | 5 | Copyright (c) 2017 Teknic Inc. This work is free to use, copy and distribute under the terms of the standard 6 | MIT permissive software license which can be found at https://opensource.org/licenses/MIT 7 | */ 8 | 9 | //Import Required libraries 10 | #include 11 | #include 12 | 13 | // initialize a ClearPathMotorSD Motor 14 | ClearPathMotorSD X; 15 | 16 | //initialize the controller and pass the reference to the motor we are controlling 17 | ClearPathStepGen machine(&X); 18 | 19 | // the setup routine runs once when you press reset: 20 | void setup() 21 | { 22 | //Begin Serial Communication // NOTE: If communication lags, consider increasing baud rate 23 | Serial.begin(9600); 24 | 25 | //X.attach(9); //attach motor so Step/B is connected to pin 9 26 | //X.attach(8,9); //Direction/A is pin 8, Step/B is pin 9 27 | //X.attach(8,9,6); //Direction/A is pin 8, Step/B is pin 9, Enable is pin 6 28 | X.attach(8,9,6,4); //Direction/A is pin 8, Step/B is pin 9, Enable is pin 6, HLFB is pin 4 29 | 30 | // Set max Velocity. Parameter can be between 2 and 100,000 steps/sec 31 | X.setMaxVel(100000); 32 | 33 | // Set max Acceleration. Parameter can be between 4000 and 2,000,000 steps/sec/sec 34 | X.setMaxAccel(2000000); 35 | 36 | // Enable motor, reset the motor position to 0 37 | X.enable(); 38 | 39 | delay(100); 40 | 41 | // Set up the ISR to constantly update motor position. All motor(s) must be attached, and enabled before this function is called. 42 | machine.Start(); 43 | 44 | 45 | } 46 | 47 | // the loop routine runs over and over again forever: 48 | void loop() 49 | { 50 | // Move the motor forward 10,000 steps 51 | X.move(10000); 52 | Serial.println("Move Start"); 53 | 54 | // wait until the command is finished and The motor's HLFB asserts 55 | while(!X.commandDone()||!X.readHLFB()) //just use command done if not using motor feedback 56 | { } 57 | Serial.println("Move Done"); 58 | delay(1000); 59 | 60 | // Move the motor backwards 10,000 steps 61 | X.move(-10000); 62 | Serial.println("Negative Move Begins"); 63 | 64 | // wait until the command is finished and The motor's HLFB asserts 65 | while(!X.commandDone()||!X.readHLFB()) //just use command done if not using motor feedback 66 | { } 67 | Serial.println("Move Done"); 68 | delay(1000); 69 | 70 | 71 | } -------------------------------------------------------------------------------- /Arduino Uno/ClearPathStepGen/Keywords.txt: -------------------------------------------------------------------------------- 1 | ClearPathStepGen KEYWORD1 2 | Start KEYWORD1 3 | Stop KEYWORD1 4 | ClearPathMotorSD KEYWORD1 5 | disable KEYWORD1 6 | enable KEYWORD1 7 | readHLFB KEYWORD1 8 | attach KEYWORD1 9 | stopMove KEYWORD1 10 | move KEYWORD1 11 | moveFast KEYWORD1 12 | commandDone KEYWORD1 13 | getCommandedPosition KEYWORD1 14 | setMaxVel KEYWORD1 15 | setMaxAccel KEYWORD1 16 | PinA KEYWORD2 17 | PinB KEYWORD2 18 | PinE KEYWORD2 19 | PinH KEYWORD2 20 | CommandX KEYWORD2 21 | AbsPosition KEYWORD2 22 | Enabled KEYWORD2 -------------------------------------------------------------------------------- /Arduino Uno/ClearPathStepGen/ReadMe.txt: -------------------------------------------------------------------------------- 1 | This Library sends pulsed step and Direction signals to ClearPath motors to precisly control position, and velocity of up to 6 motors simulateously up to 4000RPM. The methodology used to create the pulse step and direction signals is not compatible with stepper motors, or with other servo systems. The pulsed step and direction also requires a RAS setting of at least 16 ms on all ClearPath motors, a longer RAS will results in quieter motion. 2 | 3 | This library defines two classes used to manage and control the motors:ClearPathMotorSD, and ClearPathStepGen. 4 | 5 | The ClearPathMotorSD class is used to manage an individual motor including setting up pins, commanding moves, setting velocity/acceleration etc. The following is a list of commands in this class: 6 | 7 | --- ClearPathMotorSD - default constructor for initializing the motor 8 | 9 | 10 | --- attach() - Attachs pins to this motor, and declares them as input/outputs 11 | 12 | 13 | --- stopMove() - Interupts the current move, the motor may abruptly stop 14 | 15 | 16 | --- move() - sets the maximum veloctiy 17 | 18 | 19 | --- disable() - disables the motor 20 | 21 | 22 | --- enable() - enables the motor 23 | 24 | 25 | --- getCommandedPosition() - Returns the absolute cmomanded position where the position on enable=0 26 | 27 | 28 | --- readHLFB() - Returns the value of the motor's HLFB Pin 29 | 30 | 31 | --- setMaxVel() - sets the maximum veloctiy 32 | 33 | 34 | --- setMaxAccel() - sets the acceleration 35 | 36 | 37 | --- commandDone() - returns wheter or not there is a valid current command 38 | 39 | 40 | 41 | The ClearPathStepGen class is the class which manages the sending of the pulsed step and direction signals to all motors. This is accomplished by setting up a Timer based ISR at around 2kHz (using Timer2), and directly writing to the I/O register Port B. Becuase only PORTB is used to send step signals, the B input of the ClearPath motors must be connected to pins 8-13 on an Arduino Uno. Unused pins on PORTB may be used for other function without interfereing with this library. 42 | 43 | NOTE: If you are using another type of arduino besides the UNO, the ClearPathStepGen must be modified to output on a different PORT and/or the Contrustor function must be modified to correctly relate the pin numbers to the bits of the I/O Resister you would like to use. For example, 44 | 45 | In an Arduino Mega, PORTA refers to pins, 22-29, so to modify this library to use a Mega simply: 46 | 47 | 1) Do a find/replace all replacing "PORTB" with "PORTA" (case sensitive, ignore quotes). 48 | 49 | 2) Do a find/replace all replacing "->PinB-8" with "->PinB-22" (case sensitive, ignore quotes). 50 | 51 | After this, you could use an Arduino Mega and connect input B to pins 22-29 52 | 53 | 54 | --------------------------------------------------------------------------------