From dc1f236e02ead6341e4b6152a2b01b7ea381d5cf Mon Sep 17 00:00:00 2001 From: Blokkendoos Date: Tue, 15 May 2018 01:16:39 +0200 Subject: [PATCH] Detab Arduino sketch --- SphereBot Arduino/SphereBot/SoftwareServo.cpp | 139 +++++---- SphereBot Arduino/SphereBot/SoftwareServo.h | 5 +- SphereBot Arduino/SphereBot/SphereBot.ino | 268 ++++++++++-------- SphereBot Arduino/SphereBot/StepperModel.cpp | 87 +++--- SphereBot Arduino/SphereBot/StepperModel.h | 2 - SphereBot Arduino/SphereBot/TimerOne.cpp | 168 +++++------ SphereBot Arduino/SphereBot/TimerOne.h | 11 +- 7 files changed, 346 insertions(+), 334 deletions(-) diff --git a/SphereBot Arduino/SphereBot/SoftwareServo.cpp b/SphereBot Arduino/SphereBot/SoftwareServo.cpp index 6b3723d..07ffdec 100644 --- a/SphereBot Arduino/SphereBot/SoftwareServo.cpp +++ b/SphereBot Arduino/SphereBot/SoftwareServo.cpp @@ -4,7 +4,7 @@ SoftwareServo *SoftwareServo::first; #define NO_ANGLE (0xff) -SoftwareServo::SoftwareServo() : pin(0),angle(NO_ANGLE),pulse0(0),min16(34),max16(150),next(0) +SoftwareServo::SoftwareServo() : pin(0), angle(NO_ANGLE), pulse0(0), min16(34), max16(150), next(0) {} void SoftwareServo::setMinimumPulse(uint16_t t) @@ -24,105 +24,104 @@ uint8_t SoftwareServo::attach(int pinArg) pulse0 = 0; next = first; first = this; - digitalWrite(pin,0); - pinMode(pin,OUTPUT); + digitalWrite(pin, 0); + pinMode(pin, OUTPUT); return 1; } void SoftwareServo::detach() { - for ( SoftwareServo **p = &first; *p != 0; p = &((*p)->next) ) { - if ( *p == this) { - *p = this->next; - this->next = 0; - return; - } + for (SoftwareServo **p=&first; *p!=0; p=&((*p)->next) ) { + if (*p == this) { + *p = this->next; + this->next = 0; + return; } + } } void SoftwareServo::write(int angleArg) { - if ( angleArg < 0) angleArg = 0; - if ( angleArg > 180) angleArg = 180; - angle = angleArg; - // bleh, have to use longs to prevent overflow, could be tricky if always a 16MHz clock, but not true - // That 64L on the end is the TCNT0 prescaler, it will need to change if the clock's prescaler changes, - // but then there will likely be an overflow problem, so it will have to be handled by a human. - pulse0 = (min16*16L*clockCyclesPerMicrosecond() + (max16-min16)*(16L*clockCyclesPerMicrosecond())*angle/180L)/64L; + if (angleArg < 0) angleArg = 0; + if (angleArg > 180) angleArg = 180; + angle = angleArg; + // bleh, have to use longs to prevent overflow, could be tricky if always a 16MHz clock, but not true + // That 64L on the end is the TCNT0 prescaler, it will need to change if the clock's prescaler changes, + // but then there will likely be an overflow problem, so it will have to be handled by a human. + pulse0 = (min16*16L*clockCyclesPerMicrosecond() + (max16-min16)*(16L*clockCyclesPerMicrosecond())*angle/180L)/64L; } uint8_t SoftwareServo::read() { - return angle; + return angle; } uint8_t SoftwareServo::attached() { - for ( SoftwareServo *p = first; p != 0; p = p->next ) { - if ( p == this) return 1; - } - return 0; + for (SoftwareServo *p=first; p!=0; p=p->next ) { + if (p == this) return 1; + } + return 0; } void SoftwareServo::refresh() { - uint8_t count = 0, i = 0; - uint16_t base = 0; - SoftwareServo *p; - static unsigned long lastRefresh = 0; - unsigned long m = millis(); + uint8_t count = 0, i = 0; + uint16_t base = 0; + SoftwareServo *p; + static unsigned long lastRefresh = 0; + unsigned long m = millis(); - // if we haven't wrapped millis, and 20ms have not passed, then don't do anything - if ( m >= lastRefresh && m < lastRefresh + 20) return; - lastRefresh = m; + // if we haven't wrapped millis, and 20ms have not passed, then don't do anything + if (m >= lastRefresh && m < lastRefresh + 20) return; + lastRefresh = m; - for ( p = first; p != 0; p = p->next ) if ( p->pulse0) count++; - if ( count == 0) return; + for (p=first; p!=0; p=p->next ) if (p->pulse0) count++; + if (count == 0) return; - // gather all the SoftwareServos in an array - SoftwareServo *s[count]; - for ( p = first; p != 0; p = p->next ) if ( p->pulse0) s[i++] = p; + // gather all the SoftwareServos in an array + SoftwareServo *s[count]; + for (p=first; p !=0; p=p->next ) if (p->pulse0) s[i++] = p; - // bubblesort the SoftwareServos by pulse time, ascending order - for(;;) { - uint8_t moved = 0; - for ( i = 1; i < count; i++) { - if ( s[i]->pulse0 < s[i-1]->pulse0) { - SoftwareServo *t = s[i]; - s[i] = s[i-1]; - s[i-1] = t; - moved = 1; - } - } - if ( !moved) break; + // bubblesort the SoftwareServos by pulse time, ascending order + for(;;) { + uint8_t moved = 0; + for (i = 1; i < count; i++) { + if (s[i]->pulse0 < s[i-1]->pulse0) { + SoftwareServo *t = s[i]; + s[i] = s[i-1]; + s[i-1] = t; + moved = 1; + } } + if (!moved) break; + } - // turn on all the pins - // Note the timing error here... when you have many SoftwareServos going, the - // ones at the front will get a pulse that is a few microseconds too long. - // Figure about 4uS/SoftwareServo after them. This could be compensated, but I feel - // it is within the margin of error of software SoftwareServos that could catch - // an extra interrupt handler at any time. - for ( i = 0; i < count; i++) digitalWrite( s[i]->pin, 1); + // turn on all the pins + // Note the timing error here... when you have many SoftwareServos going, the + // ones at the front will get a pulse that is a few microseconds too long. + // Figure about 4uS/SoftwareServo after them. This could be compensated, but I feel + // it is within the margin of error of software SoftwareServos that could catch + // an extra interrupt handler at any time. + for (i=0; ipin, 1); - uint8_t start = TCNT0; - uint8_t now = start; - uint8_t last = now; + uint8_t start = TCNT0; + uint8_t now = start; + uint8_t last = now; - // Now wait for each pin's time in turn.. - for ( i = 0; i < count; i++) { - uint16_t go = start + s[i]->pulse0; + // Now wait for each pin's time in turn.. + for (i=0; ipulse0; - // loop until we reach or pass 'go' time - for (;;) { - now = TCNT0; - if ( now < last) base += 256; - last = now; - - if ( base+now > go) { - digitalWrite( s[i]->pin,0); - break; - } - } + // loop until we reach or pass 'go' time + for (;;) { + now = TCNT0; + if (now < last) base += 256; + last = now; + if (base+now > go) { + digitalWrite(s[i]->pin, 0); + break; + } } + } } diff --git a/SphereBot Arduino/SphereBot/SoftwareServo.h b/SphereBot Arduino/SphereBot/SoftwareServo.h index f380e48..5eb6216 100644 --- a/SphereBot Arduino/SphereBot/SoftwareServo.h +++ b/SphereBot Arduino/SphereBot/SoftwareServo.h @@ -14,6 +14,7 @@ class SoftwareServo uint8_t max16; // maximum pulse, 16uS units, 0-4ms range (default is 150) class SoftwareServo *next; static SoftwareServo* first; + public: SoftwareServo(); uint8_t attach(int); // attach to a pin, sets pinMode, returns 0 on failure, won't @@ -24,8 +25,8 @@ class SoftwareServo uint8_t attached(); void setMinimumPulse(uint16_t); // pulse length for 0 degrees in microseconds, 540uS default void setMaximumPulse(uint16_t); // pulse length for 180 degrees in microseconds, 2400uS default - static void refresh(); // must be called at least every 50ms or so to keep servo alive - // you can call more often, it won't happen more than once every 20ms + static void refresh(); // must be called at least every 50ms or so to keep servo alive + // you can call more often, it won't happen more than once every 20ms }; #endif diff --git a/SphereBot Arduino/SphereBot/SphereBot.ino b/SphereBot Arduino/SphereBot/SphereBot.ino index 04da316..dd2ba3b 100644 --- a/SphereBot Arduino/SphereBot/SphereBot.ino +++ b/SphereBot Arduino/SphereBot/SphereBot.ino @@ -1,7 +1,3 @@ - - - - /* * Original Code: Copyright 2011 by Eberhard Rensch * @@ -35,26 +31,24 @@ #include "StepperModel.h" #include "config.h" - #define TIMER_DELAY 1024 - #define VERSIONCODE "Spherebot 2.1" StepperModel xAxisStepper( - XAXIS_DIR_PIN, XAXIS_STEP_PIN, XAXIS_ENABLE_PIN, XAXIS_ENDSTOP_PIN, - XAXIS_MS1_PIN, XAXIS_MS2_PIN, XAXIS_MS3_PIN, - XAXIS_SLP_PIN, XAXIS_RST_PIN, - XAXIS_VMS1, XAXIS_VMS2, XAXIS_VMS3, - XAXIS_MIN_STEPCOUNT, XAXIS_MAX_STEPCOUNT, - XAXIS_STEPS_PER_FULL_ROTATION, XAXIS_MICROSTEPPING); + XAXIS_DIR_PIN, XAXIS_STEP_PIN, XAXIS_ENABLE_PIN, XAXIS_ENDSTOP_PIN, + XAXIS_MS1_PIN, XAXIS_MS2_PIN, XAXIS_MS3_PIN, + XAXIS_SLP_PIN, XAXIS_RST_PIN, + XAXIS_VMS1, XAXIS_VMS2, XAXIS_VMS3, + XAXIS_MIN_STEPCOUNT, XAXIS_MAX_STEPCOUNT, + XAXIS_STEPS_PER_FULL_ROTATION, XAXIS_MICROSTEPPING); StepperModel rotationStepper( - YAXIS_DIR_PIN, YAXIS_STEP_PIN, YAXIS_ENABLE_PIN, YAXIS_ENDSTOP_PIN, - YAXIS_MS1_PIN, YAXIS_MS2_PIN, YAXIS_MS3_PIN, - YAXIS_SLP_PIN, YAXIS_RST_PIN, - YAXIS_VMS1, YAXIS_VMS2, YAXIS_VMS3, - YAXIS_MIN_STEPCOUNT, YAXIS_MIN_STEPCOUNT, - YAXIS_STEPS_PER_FULL_ROTATION, YAXIS_MICROSTEPPING); + YAXIS_DIR_PIN, YAXIS_STEP_PIN, YAXIS_ENABLE_PIN, YAXIS_ENDSTOP_PIN, + YAXIS_MS1_PIN, YAXIS_MS2_PIN, YAXIS_MS3_PIN, + YAXIS_SLP_PIN, YAXIS_RST_PIN, + YAXIS_VMS1, YAXIS_VMS2, YAXIS_VMS3, + YAXIS_MIN_STEPCOUNT, YAXIS_MIN_STEPCOUNT, + YAXIS_STEPS_PER_FULL_ROTATION, YAXIS_MICROSTEPPING); SoftwareServo servo; boolean servoEnabled=true; @@ -71,7 +65,7 @@ int serial_count = 0; // current length of command char *strchr_pointer; // just a pointer to find chars in the cmd string like X, Y, Z, E, etc boolean comment_mode = false; -int next_command_request_counter = 0; //if this counter reaches the maximum then a "ok" is sent to request the nex command +int next_command_request_counter = 0; //if this counter reaches the maximum then a "ok" is sent to request the nex command int next_command_request_maximum = 1000; // end comm variables @@ -86,79 +80,91 @@ double yscaling = Y_SCALING_FACTOR; const double maxFeedrate = 2000.; -// ------ - void setup() { - Serial.begin(BAUDRATE); - Serial.print(VERSIONCODE); - Serial.print("\n"); - - clear_buffer(); + // disable the Ethernet chip/SD card + pinMode(4, OUTPUT); + digitalWrite(4, HIGH); - servo.attach(SERVO_PIN_1); - servo.write(DEFAULT_PEN_UP_POSITION); - - if(servoEnabled) + // flash ALT LED + pinMode(ALT_PIN, OUTPUT); + digitalWrite(ALT_PIN, HIGH); + delay(150); + digitalWrite(ALT_PIN, LOW); + delay(150); + digitalWrite(ALT_PIN, HIGH); + delay(150); + digitalWrite(ALT_PIN, LOW); + + Serial.begin(BAUDRATE); + Serial.print(VERSIONCODE); + Serial.print("\n"); + + clear_buffer(); + + servo.attach(SERVO_PIN_1); + servo.write(DEFAULT_PEN_UP_POSITION); + + if (servoEnabled) + { + for(int i=0; i<100; i++) { - for(int i=0;i<100;i++) - { - SoftwareServo::refresh(); - delay(4); - } + SoftwareServo::refresh(); + delay(4); } - - //--- Activate the PWM timer - Timer1.initialize(TIMER_DELAY); // Timer for updating pwm pins - Timer1.attachInterrupt(doInterrupt); - + } + + // activate the PWM timer + Timer1.initialize(TIMER_DELAY); // Timer for updating pwm pins + Timer1.attachInterrupt(doInterrupt); + #ifdef AUTO_HOMING - xAxisStepper.autoHoming(); - xAxisStepper.setTargetPosition(0.); - commitSteppers(maxFeedrate); - delay(2000); - xAxisStepper.enableStepper(false); + xAxisStepper.autoHoming(); + xAxisStepper.setTargetPosition(0.); + commitSteppers(maxFeedrate); + delay(2000); + xAxisStepper.enableStepper(false); #endif } void loop() // input loop, looks for manual input and then checks to see if and serial commands are coming in { get_command(); // check for Gcodes - if(servoEnabled) + if (servoEnabled) SoftwareServo::refresh(); Serial.flush(); } -//--- Interrupt-Routine: Move the steppers +// Interrupt-Routine: Move the steppers void doInterrupt() { - if(isRunning) + if (isRunning) { - if(next_command_request_counter++ > next_command_request_maximum) - { - //Serial.print("forced ok\n"); - next_command_request_counter = 0; - } - if (intervals_remaining-- == 0) - isRunning = false; - else - { - rotationStepper.doStep(intervals); - xAxisStepper.doStep(intervals); - } + if (next_command_request_counter++ > next_command_request_maximum) + { + //Serial.print("forced ok\n"); + next_command_request_counter = 0; + } + if (intervals_remaining-- == 0) + isRunning = false; + else + { + rotationStepper.doStep(intervals); + xAxisStepper.doStep(intervals); + } } } void commitSteppers(double speedrate) { long deltaStepsX = xAxisStepper.delta; - if(deltaStepsX != 0L) + if (deltaStepsX != 0L) { xAxisStepper.enableStepper(true); } long deltaStepsY = rotationStepper.delta; - if(deltaStepsY != 0L) + if (deltaStepsY != 0L) { rotationStepper.enableStepper(true); } @@ -166,10 +172,10 @@ void commitSteppers(double speedrate) double deltaDistanceX = xAxisStepper.targetPosition-xAxisStepper.getCurrentPosition(); double deltaDistanceY = rotationStepper.targetPosition-rotationStepper.getCurrentPosition(); - + // how long is our line length? double distance = sqrt(deltaDistanceX*deltaDistanceX+deltaDistanceY*deltaDistanceY); - + // compute number of intervals for this move double sub1 = (60000.* distance / speedrate); double sub2 = sub1 * 1000.; @@ -191,7 +197,7 @@ void commitSteppers(double speedrate) // Serial.print(masterSteps); // Serial.print(" dDistX:"); // Serial.print(deltaDistanceX); -// Serial.print(" dDistY:"); +// Serial.print(" dDistY:"); // Serial.print(deltaDistanceY); // Serial.print(" distance:"); // Serial.print(distance); @@ -219,7 +225,7 @@ void get_command() // gets commands from serial connection and then calls up sub if (serial_char == '\n' || serial_char == '\r') // end of a command character { - next_command_request_counter = 0; + next_command_request_counter = 0; buffer[serial_count]=0; process_commands(buffer, serial_count); clear_buffer(); @@ -270,24 +276,23 @@ boolean getValue(char key, char command[], double* value) void check_for_version_controll(char command) { - if(command == 'V') + if (command == 'V') { Serial.print(VERSIONCODE); Serial.print("\n"); } } - void process_commands(char command[], int command_length) // deals with standardized input from serial connection { double nVal; boolean hasNVal = getValue('N', command, &nVal); - //if(hasNVal) {Serial.println("linenumber detected");}; + //if (hasNVal) {Serial.println("linenumber detected");}; double getcs; boolean hasCS = getValue('*', command, &getcs); - //if(hasCS) {Serial.println("checksum detected");}; + //if (hasCS) {Serial.println("checksum detected");}; // checksum code from reprap wiki int cs = 0; @@ -296,25 +301,25 @@ void process_commands(char command[], int command_length) // deals with standard cs = cs ^ command[j]; cs &= 0xff; // Defensive programming... - if(!(cs == (int)getcs || hasCS == false)) // if checksum does not match + if (!(cs == (int)getcs || hasCS == false)) // if checksum does not match { Serial.print("rs "); - Serial.print((int)getcs); + Serial.print((int)getcs); //Serial.print((int)nVal); Serial.print("\n"); - //Serial.flush(); + //Serial.flush(); } - else //continue if checksum matches or none detected + else //continue if checksum matches or none detected { //Serial.println("checksum match "); - j=0; + j = 0; while (j < MAX_CMD_SIZE ) { if ((command[j] == 'G') || command[j] == 'M') {break;} j++; } - if(command_length == 1) + if (command_length == 1) { check_for_version_controll(command[0]); } @@ -328,43 +333,51 @@ void process_commands(char command[], int command_length) // deals with standard double xVal; boolean hasXVal = getValue('X', command, &xVal); - if(hasXVal) xVal*=zoom*xscaling; + if (hasXVal) xVal *= zoom*xscaling; + double yVal; boolean hasYVal = getValue('Y', command, &yVal); - if(hasYVal) yVal*=zoom*yscaling; + if (hasYVal) yVal *= zoom*yscaling; + + double zVal; + boolean hasZVal = getValue('Z', command, &zVal); + double iVal; boolean hasIVal = getValue('I', command, &iVal); - if(hasIVal) iVal*=zoom; + if (hasIVal) iVal *= zoom; + double jVal; boolean hasJVal = getValue('J', command, &jVal); - if(hasJVal) jVal*=zoom; + if (hasJVal) jVal *= zoom; + double rVal; boolean hasRVal = getValue('R', command, &rVal); - if(hasRVal) rVal*=zoom; + if (hasRVal) rVal *= zoom; + double pVal; boolean hasPVal = getValue('P', command, &pVal); getValue('F', command, &feedrate); - xVal+=currentOffsetX; - yVal+=currentOffsetY; + xVal += currentOffsetX; + yVal += currentOffsetY; - if(absoluteMode) + if (absoluteMode) { - if(hasXVal) - tempX=xVal; - if(hasYVal) - tempY=yVal; + if (hasXVal) + tempX = xVal; + if (hasYVal) + tempY = yVal; } else { - if(hasXVal) - tempX+=xVal; - if(hasYVal) - tempY+=yVal; + if (hasXVal) + tempX += xVal; + if (hasYVal) + tempY += yVal; } - switch(codenum) + switch (codenum) { case 0: // G0, Rapid positioning xAxisStepper.setTargetPosition(tempX); @@ -378,25 +391,25 @@ void process_commands(char command[], int command_length) // deals with standard break; case 2: // G2, Clockwise arc case 3: // G3, Counterclockwise arc - if(hasIVal && hasJVal) + if (hasIVal && hasJVal) { double centerX=xAxisStepper.getCurrentPosition()+iVal; double centerY=rotationStepper.getCurrentPosition()+jVal; drawArc(centerX, centerY, tempX, tempY, (codenum==2)); } - else if(hasRVal) + else if (hasRVal) { //drawRadius(tempX, tempY, rVal, (codenum==2)); } break; case 4: // G4, Delay P ms - if(hasPVal) + if (hasPVal) { unsigned long endDelay = millis()+ (unsigned long)pVal; while(millis()180.) - { - value=DEFAULT_PEN_UP_POSITION; - servo.write((int)value); - for(int i=0;i<100;i++) - { - SoftwareServo::refresh(); - delay(2); - } - servoEnabled=false; - } - servo.write((int)value); + moveServo(value); } break; case 400: // Propretary: Reset X-Axis-Stepper settings to new object diameter - if(getValue('S', command, &value)) + if (getValue('S', command, &value)) { xAxisStepper.resetSteppersForObjectDiameter(value); xAxisStepper.setTargetPosition(0.); @@ -458,7 +457,7 @@ void process_commands(char command[], int command_length) // deals with standard break; case 401: // Propretary: Reset Y-Axis-Stepper settings to new object diameter - if(getValue('S', command, &value)) + if (getValue('S', command, &value)) { rotationStepper.resetSteppersForObjectDiameter(value); rotationStepper.setTargetPosition(0.); @@ -469,13 +468,14 @@ void process_commands(char command[], int command_length) // deals with standard break; case 402: // Propretary: Reset Y-Axis-Stepper settings to new object diameter - if(getValue('S', command, &value)) + if (getValue('S', command, &value)) { zoom = value/100; } break; + default: - break; + break; } } @@ -492,6 +492,25 @@ void process_commands(char command[], int command_length) // deals with standard } } +void moveServo(double value) +{ + servoEnabled = true; + if (value < 0.) + value = 0.; + else if (value > 180.) + { + value = DEFAULT_PEN_UP_POSITION; + servo.write((int)value); + for(int i=0; i<100; i++) + { + SoftwareServo::refresh(); + delay(2); + } + servoEnabled = false; + } + servo.write((int)value); +} + /* This code was ported from the Makerbot/ReplicatorG java sources */ void drawArc(double centerX, double centerY, double endpointX, double endpointY, boolean clockwise) { @@ -516,7 +535,6 @@ void drawArc(double centerX, double centerY, double endpointX, double endpointY, bX = endpointX - centerX; bY = endpointY - centerY; - // Clockwise if (clockwise) { angleA = atan2(bY, bX); angleB = atan2(aY, aX); @@ -534,7 +552,7 @@ void drawArc(double centerX, double centerY, double endpointX, double endpointY, if (angleB <= angleA) angleB += 2. * M_PI; angle = angleB - angleA; - + // calculate a couple useful things. radius = sqrt(aX * aX + aY * aY); length = radius * angle; @@ -554,24 +572,24 @@ void drawArc(double centerX, double centerY, double endpointX, double endpointY, for (s = 1; s <= steps; s++) { // Forwards for CCW, backwards for CW - if (!clockwise) - step = s; + if (clockwise) + step = steps - s; else - step = steps - s; + step = s; // calculate our waypoint. newPointX = centerX + radius * cos(angleA + angle * ((double) step / steps)); - newPointY= centerY + radius * sin(angleA + angle * ((double) step / steps)); + newPointY= centerY + radius * sin(angleA + angle * ((double) step / steps)); // start the move xAxisStepper.setTargetPosition(newPointX); rotationStepper.setTargetPosition(newPointY); commitSteppers(feedrate); - while(isRunning) + while (isRunning) { delay(1); - if(servoEnabled) + if (servoEnabled) SoftwareServo::refresh(); }; } diff --git a/SphereBot Arduino/SphereBot/StepperModel.cpp b/SphereBot Arduino/SphereBot/StepperModel.cpp index b2474f1..353fc09 100644 --- a/SphereBot Arduino/SphereBot/StepperModel.cpp +++ b/SphereBot Arduino/SphereBot/StepperModel.cpp @@ -30,8 +30,8 @@ StepperModel::StepperModel( long minSC, long maxSC, double in_kStepsPerRevolution, int in_kMicroStepping) { - kStepsPerRevolution=in_kStepsPerRevolution; - kMicroStepping=in_kMicroStepping; + kStepsPerRevolution = in_kStepsPerRevolution; + kMicroStepping = in_kMicroStepping; dirPin = inDirPin; stepPin = inStepPin; @@ -46,35 +46,32 @@ StepperModel::StepperModel( minStepCount=minSC; maxStepCount=maxSC; - pinMode(dirPin, OUTPUT); - pinMode(stepPin, OUTPUT); - pinMode(enablePin, OUTPUT); - if((sleepPin >=0)) - { + pinMode(dirPin, OUTPUT); + pinMode(stepPin, OUTPUT); + pinMode(enablePin, OUTPUT); + + if (sleepPin >=0) { pinMode(sleepPin, OUTPUT); digitalWrite(sleepPin, HIGH); } - if((resetPin >=0)) - { + if (resetPin >=0) { pinMode(resetPin, OUTPUT); digitalWrite(resetPin, HIGH); } - if(endStopPin>=0) - pinMode(endStopPin, INPUT); - if((ms1Pin >=0)) - { - pinMode(ms1Pin, OUTPUT); - digitalWrite(ms1Pin, vms1); + if (endStopPin>=0) { + pinMode(endStopPin, INPUT); } - if((ms2Pin >=0)) - { - pinMode(ms2Pin, OUTPUT); - digitalWrite(ms2Pin, vms1); + if (ms1Pin >=0) { + pinMode(ms1Pin, OUTPUT); + digitalWrite(ms1Pin, vms1); } - if((ms3Pin >=0)) - { - pinMode(ms3Pin, OUTPUT); - digitalWrite(ms3Pin, vms1); + if (ms2Pin >=0) { + pinMode(ms2Pin, OUTPUT); + digitalWrite(ms2Pin, vms1); + } + if (ms3Pin >=0) { + pinMode(ms3Pin, OUTPUT); + digitalWrite(ms3Pin, vms1); } digitalWrite(dirPin, LOW); @@ -91,7 +88,7 @@ void StepperModel::resetSteppersForObjectDiameter(double diameter) { // Calculate the motor steps required to move per mm. steps_per_mm = (int)((kStepsPerRevolution/(diameter*M_PI))*kMicroStepping+0.5); - if(endStopPin>=0) + if (endStopPin>=0) { #ifdef AUTO_HOMING autoHoming(); @@ -105,12 +102,10 @@ void StepperModel::resetSteppersForObjectDiameter(double diameter) long StepperModel::getStepsForMM(double mm) { long steps = (long)(steps_per_mm*mm); - // Serial.print("steps for "); // Serial.print(mm); // Serial.print(" mm: "); // Serial.println(steps); - return steps; } @@ -126,8 +121,8 @@ void StepperModel::setTargetStepcount(long tsc) enableStepper(true); } if (delta < 0) { - delta = -delta; - direction = false; + delta = -delta; + direction = false; } }*/ @@ -142,14 +137,14 @@ void StepperModel::setTargetPosition(double pos) enableStepper(true); } if (delta < 0) { - delta = -delta; - direction = false; + delta = -delta; + direction = false; } } double StepperModel::getCurrentPosition() { - return (double)currentStepcount/steps_per_mm; + return (double)currentStepcount/steps_per_mm; } void StepperModel::enableStepper(bool enabled) @@ -160,26 +155,28 @@ void StepperModel::enableStepper(bool enabled) void StepperModel::resetStepper() { enableStepper(false); - currentStepcount=0; - targetStepcount=0; - delta=0; + currentStepcount = 0; + targetStepcount = 0; + delta = 0; } void StepperModel::doStep(long intervals) { counter += delta; - if (counter >= 0) { + if (counter >= 0) + { digitalWrite(dirPin, direction?HIGH:LOW); counter -= intervals; - if (direction) { - if(maxStepCount==0 || currentStepcount<=maxStepCount) - { + if (direction) + { + if (maxStepCount == 0 || currentStepcount<=maxStepCount) { digitalWrite(stepPin, HIGH); currentStepcount++; } - } else { - if(minStepCount==0 || currentStepcount>=minStepCount) - { + } + else + { + if (minStepCount == 0 || currentStepcount>=minStepCount) { digitalWrite(stepPin, HIGH); currentStepcount--; } @@ -196,11 +193,11 @@ void StepperModel::autoHoming() while(digitalRead(endStopPin)) { - digitalWrite(stepPin, HIGH); - digitalWrite(stepPin, LOW); - delay(1); + digitalWrite(stepPin, HIGH); + digitalWrite(stepPin, LOW); + delay(1); } - currentStepcount= minStepCount-16; + currentStepcount = minStepCount-16; } #endif diff --git a/SphereBot Arduino/SphereBot/StepperModel.h b/SphereBot Arduino/SphereBot/StepperModel.h index e004708..a93db2c 100644 --- a/SphereBot Arduino/SphereBot/StepperModel.h +++ b/SphereBot Arduino/SphereBot/StepperModel.h @@ -24,7 +24,6 @@ class StepperModel { private: - int dirPin; int stepPin; int enablePin; @@ -68,7 +67,6 @@ public: #ifdef AUTO_HOMING void autoHoming(); #endif - void setTargetPosition(double pos); double getCurrentPosition(); diff --git a/SphereBot Arduino/SphereBot/TimerOne.cpp b/SphereBot Arduino/SphereBot/TimerOne.cpp index efede8d..63f9cfb 100644 --- a/SphereBot Arduino/SphereBot/TimerOne.cpp +++ b/SphereBot Arduino/SphereBot/TimerOne.cpp @@ -19,17 +19,17 @@ * - renamed startBottom() to start(). This breaks some old code that expects start to continue counting where it left off * * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . * * See Google Code project http://code.google.com/p/arduino-timerone/ for latest */ @@ -54,19 +54,19 @@ void TimerOne::initialize(long microseconds) } -void TimerOne::setPeriod(long microseconds) // AR modified for atomic access +void TimerOne::setPeriod(long microseconds) // AR modified for atomic access { long cycles = (F_CPU / 2000000) * microseconds; // the counter runs backwards after TOP, interrupt is at BOTTOM so divide microseconds by 2 - if(cycles < RESOLUTION) clockSelectBits = _BV(CS10); // no prescale, full xtal - else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11); // prescale by /8 - else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11) | _BV(CS10); // prescale by /64 - else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12); // prescale by /256 - else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12) | _BV(CS10); // prescale by /1024 + if (cycles < RESOLUTION) clockSelectBits = _BV(CS10); // no prescale, full xtal + else if ((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11); // prescale by /8 + else if ((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11) | _BV(CS10); // prescale by /64 + else if ((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12); // prescale by /256 + else if ((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12) | _BV(CS10); // prescale by /1024 else cycles = RESOLUTION - 1, clockSelectBits = _BV(CS12) | _BV(CS10); // request was out of bounds, set as maximum - oldSREG = SREG; - cli(); // Disable interrupts for 16 bit register access + oldSREG = SREG; + cli(); // Disable interrupts for 16 bit register access ICR1 = pwmPeriod = cycles; // ICR1 is TOP in p & f correct pwm mode SREG = oldSREG; @@ -83,79 +83,79 @@ void TimerOne::setPwmDuty(char pin, int duty) oldSREG = SREG; cli(); - if(pin == 1 || pin == 9) OCR1A = dutyCycle; - else if(pin == 2 || pin == 10) OCR1B = dutyCycle; + if (pin == 1 || pin == 9) OCR1A = dutyCycle; + else if (pin == 2 || pin == 10) OCR1B = dutyCycle; SREG = oldSREG; } void TimerOne::pwm(char pin, int duty, long microseconds) // expects duty cycle to be 10 bit (1024) { - if(microseconds > 0) setPeriod(microseconds); - if(pin == 1 || pin == 9) { + if (microseconds > 0) setPeriod(microseconds); + if (pin == 1 || pin == 9) { DDRB |= _BV(PORTB1); // sets data direction register for pwm output pin TCCR1A |= _BV(COM1A1); // activates the output pin } - else if(pin == 2 || pin == 10) { + else if (pin == 2 || pin == 10) { DDRB |= _BV(PORTB2); TCCR1A |= _BV(COM1B1); } setPwmDuty(pin, duty); - resume(); // Lex - make sure the clock is running. We don't want to restart the count, in case we are starting the second WGM - // and the first one is in the middle of a cycle + resume(); // Lex - make sure the clock is running. We don't want to restart the count, in case we are starting the second WGM + // and the first one is in the middle of a cycle } void TimerOne::disablePwm(char pin) { - if(pin == 1 || pin == 9) TCCR1A &= ~_BV(COM1A1); // clear the bit that enables pwm on PB1 - else if(pin == 2 || pin == 10) TCCR1A &= ~_BV(COM1B1); // clear the bit that enables pwm on PB2 + if (pin == 1 || pin == 9) TCCR1A &= ~_BV(COM1A1); // clear the bit that enables pwm on PB1 + else if (pin == 2 || pin == 10) TCCR1A &= ~_BV(COM1B1); // clear the bit that enables pwm on PB2 } void TimerOne::attachInterrupt(void (*isr)(), long microseconds) { - if(microseconds > 0) setPeriod(microseconds); + if (microseconds > 0) setPeriod(microseconds); isrCallback = isr; // register the user's callback with the real ISR TIMSK1 = _BV(TOIE1); // sets the timer overflow interrupt enable bit - // might be running with interrupts disabled (eg inside an ISR), so don't touch the global state + // might be running with interrupts disabled (eg inside an ISR), so don't touch the global state // sei(); - resume(); + resume(); } void TimerOne::detachInterrupt() { TIMSK1 &= ~_BV(TOIE1); // clears the timer overflow interrupt enable bit - // timer continues to count without calling the isr + // timer continues to count without calling the isr } -void TimerOne::resume() // AR suggested +void TimerOne::resume() // AR suggested { TCCR1B |= clockSelectBits; } -void TimerOne::restart() // Depricated - Public interface to start at zero - Lex 10/9/2011 +void TimerOne::restart() // Depricated - Public interface to start at zero - Lex 10/9/2011 { - start(); + start(); } -void TimerOne::start() // AR addition, renamed by Lex to reflect it's actual role +void TimerOne::start() // AR addition, renamed by Lex to reflect it's actual role { unsigned int tcnt1; TIMSK1 &= ~_BV(TOIE1); // AR added - GTCCR |= _BV(PSRSYNC); // AR added - reset prescaler (NB: shared with all 16 bit timers); + GTCCR |= _BV(PSRSYNC); // AR added - reset prescaler (NB: shared with all 16 bit timers); - oldSREG = SREG; // AR - save status register - cli(); // AR - Disable interrupts - TCNT1 = 0; - SREG = oldSREG; // AR - Restore status register - resume(); - do { // Nothing -- wait until timer moved on from zero - otherwise get a phantom interrupt - oldSREG = SREG; - cli(); - tcnt1 = TCNT1; - SREG = oldSREG; + oldSREG = SREG; // AR - save status register + cli(); // AR - Disable interrupts + TCNT1 = 0; + SREG = oldSREG; // AR - Restore status register + resume(); + do { // Nothing -- wait until timer moved on from zero - otherwise get a phantom interrupt + oldSREG = SREG; + cli(); + tcnt1 = TCNT1; + SREG = oldSREG; } while (tcnt1==0); -// TIFR1 = 0xff; // AR - Clear interrupt flags +// TIFR1 = 0xff; // AR - Clear interrupt flags // TIMSK1 = _BV(TOIE1); // sets the timer overflow interrupt enable bit } @@ -164,46 +164,46 @@ void TimerOne::stop() TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12)); // clears all clock selects bits } -unsigned long TimerOne::read() //returns the value of the timer in microseconds -{ //rember! phase and freq correct mode counts up to then down again - unsigned long tmp; // AR amended to hold more than 65536 (could be nearly double this) - unsigned int tcnt1; // AR added +unsigned long TimerOne::read() //returns the value of the timer in microseconds +{ //rember! phase and freq correct mode counts up to then down again + unsigned long tmp; // AR amended to hold more than 65536 (could be nearly double this) + unsigned int tcnt1; // AR added - oldSREG= SREG; - cli(); - tmp=TCNT1; - SREG = oldSREG; + oldSREG= SREG; + cli(); + tmp=TCNT1; + SREG = oldSREG; - char scale=0; - switch (clockSelectBits) - { - case 1:// no prescalse - scale=0; - break; - case 2:// x8 prescale - scale=3; - break; - case 3:// x64 - scale=6; - break; - case 4:// x256 - scale=8; - break; - case 5:// x1024 - scale=10; - break; - } - - do { // Nothing -- max delay here is ~1023 cycles. AR modified - oldSREG = SREG; - cli(); - tcnt1 = TCNT1; - SREG = oldSREG; - } while (tcnt1==tmp); //if the timer has not ticked yet + char scale=0; + switch (clockSelectBits) + { + case 1:// no prescalse + scale = 0; + break; + case 2:// x8 prescale + scale = 3; + break; + case 3:// x64 + scale = 6; + break; + case 4:// x256 + scale = 8; + break; + case 5:// x1024 + scale = 10; + break; + } - //if we are counting down add the top value to how far we have counted down - tmp = ( (tcnt1>tmp) ? (tmp) : (long)(ICR1-tcnt1)+(long)ICR1 ); // AR amended to add casts and reuse previous TCNT1 - return ((tmp*1000L)/(F_CPU /1000L))<tmp) ? (tmp) : (long)(ICR1-tcnt1) + (long)ICR1 ); // AR amended to add casts and reuse previous TCNT1 + return ((tmp*1000L)/(F_CPU /1000L))<< scale; } -#endif \ No newline at end of file +#endif diff --git a/SphereBot Arduino/SphereBot/TimerOne.h b/SphereBot Arduino/SphereBot/TimerOne.h index c37c682..c3c311e 100644 --- a/SphereBot Arduino/SphereBot/TimerOne.h +++ b/SphereBot Arduino/SphereBot/TimerOne.h @@ -39,24 +39,23 @@ #include #include -#define RESOLUTION 65536 // Timer1 is 16 bit +#define RESOLUTION 65536 // Timer1 is 16 bit class TimerOne { public: - // properties unsigned int pwmPeriod; unsigned char clockSelectBits; - char oldSREG; // To hold Status Register while ints disabled + char oldSREG; // To hold Status Register while ints disabled // methods void initialize(long microseconds=1000000); void start(); void stop(); void restart(); - void resume(); - unsigned long read(); + void resume(); + unsigned long read(); void pwm(char pin, int duty, long microseconds=-1); void disablePwm(char pin); void attachInterrupt(void (*isr)(), long microseconds=-1); @@ -67,4 +66,4 @@ class TimerOne }; extern TimerOne Timer1; -#endif \ No newline at end of file +#endif