mirror of
https://github.com/thunderbug1/Spherebot-Host-GUI.git
synced 2026-03-03 16:43:59 +01:00
Detab Arduino sketch
This commit is contained in:
@@ -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; i<count; i++) digitalWrite(s[i]->pin, 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; i<count; i++) {
|
||||
uint16_t go = start + s[i]->pulse0;
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Original Code: Copyright 2011 by Eberhard Rensch <http://pleasantsoftware.com/developer/3d>
|
||||
*
|
||||
@@ -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()<endDelay)
|
||||
{
|
||||
delay(1);
|
||||
if(servoEnabled)
|
||||
if (servoEnabled)
|
||||
SoftwareServo::refresh();
|
||||
}
|
||||
}
|
||||
@@ -426,28 +439,14 @@ void process_commands(char command[], int command_length) // deals with standard
|
||||
break;
|
||||
|
||||
case 300: // Servo Position
|
||||
if(getValue('S', command, &value))
|
||||
if (getValue('S', command, &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);
|
||||
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();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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))<<scale;
|
||||
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
|
||||
|
||||
//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))<< scale;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -39,24 +39,23 @@
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
#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
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user