Merge branch 'TimEvWw-master'
commit
a083d3bc06
|
@ -92,10 +92,10 @@ F |22 |P V |Write parameter
|
|||
F |23 |P V |Update parameter (during calibration)
|
||||
F |31 |P |Read status
|
||||
F |32 |P V |Write status
|
||||
F |41 |P V M |Set a value on an arduino pin
|
||||
F |42 |P M |Read a value from an arduino pin
|
||||
F |43 |P M |Set the mode of a pin in arduino
|
||||
F |44 |P V W T |Set the value V on an arduino pin, wait for time T, set value W on the arduino pin
|
||||
F |41 |P V M |Set a value on an arduino pin (digital/analog)
|
||||
F |42 |P M |Read a value from an arduino pin (digital/analog)
|
||||
F |43 |P M |Set the mode of a pin in arduino (input/output)
|
||||
F |44 |P V W T M |Set the value V on an arduino pin, wait for time T, set value W on the arduino pin (d/a)
|
||||
F |51 |E P V |Set a value on the tool mount with I2C
|
||||
F |52 |E P |Read value from the tool mount with I2C
|
||||
F |61 |P V |Set the servo on the pin (only pin 4 and 5) to the requested angle
|
||||
|
|
|
@ -209,15 +209,15 @@ double Command::getZ() {
|
|||
}
|
||||
|
||||
long Command::getA() {
|
||||
return axisValue[0];
|
||||
return axisSpeedValue[0];
|
||||
}
|
||||
|
||||
long Command::getB() {
|
||||
return axisValue[1];
|
||||
return axisSpeedValue[1];
|
||||
}
|
||||
|
||||
long Command::getC() {
|
||||
return axisValue[2];
|
||||
return axisSpeedValue[2];
|
||||
}
|
||||
|
||||
long Command::getP() {
|
||||
|
|
19
src/Config.h
19
src/Config.h
|
@ -41,25 +41,28 @@ const long MOVEMENT_INVERT_MOTOR_X_DEFAULT = 0;
|
|||
const long MOVEMENT_INVERT_MOTOR_Y_DEFAULT = 0;
|
||||
const long MOVEMENT_INVERT_MOTOR_Z_DEFAULT = 0;
|
||||
|
||||
const long MOVEMENT_STEPS_ACC_DEC_X_DEFAULT = 200;
|
||||
const long MOVEMENT_STEPS_ACC_DEC_Y_DEFAULT = 200;
|
||||
const long MOVEMENT_STEPS_ACC_DEC_Z_DEFAULT = 200;
|
||||
|
||||
const long MOVEMENT_HOME_UP_X_DEFAULT = 0;
|
||||
const long MOVEMENT_HOME_UP_Y_DEFAULT = 0;
|
||||
const long MOVEMENT_HOME_UP_Z_DEFAULT = 1;
|
||||
|
||||
// numver of steps used for acceleration or deceleration
|
||||
const long MOVEMENT_STEPS_ACC_DEC_X_DEFAULT = 200;
|
||||
const long MOVEMENT_STEPS_ACC_DEC_Y_DEFAULT = 200;
|
||||
const long MOVEMENT_STEPS_ACC_DEC_Z_DEFAULT = 200;
|
||||
|
||||
// Minimum speed in steps per second
|
||||
const long MOVEMENT_MIN_SPD_X_DEFAULT = 200;
|
||||
const long MOVEMENT_MIN_SPD_Y_DEFAULT = 200;
|
||||
const long MOVEMENT_MIN_SPD_Z_DEFAULT = 200;
|
||||
|
||||
const long MOVEMENT_MAX_SPD_X_DEFAULT = 1000;
|
||||
const long MOVEMENT_MAX_SPD_Y_DEFAULT = 1000;
|
||||
const long MOVEMENT_MAX_SPD_Z_DEFAULT = 1000;
|
||||
// Maxumum speed in steps per second
|
||||
const long MOVEMENT_MAX_SPD_X_DEFAULT = 4000;
|
||||
const long MOVEMENT_MAX_SPD_Y_DEFAULT = 4000;
|
||||
const long MOVEMENT_MAX_SPD_Z_DEFAULT = 4000;
|
||||
|
||||
const long STATUS_GENERAL_DEFAULT = 0;
|
||||
|
||||
|
||||
const String SOFTWARE_VERSION = "GENESIS V.01.03";
|
||||
const String SOFTWARE_VERSION = "GENESIS V.01.04";
|
||||
|
||||
#endif /* CONFIG_H_ */
|
||||
|
|
|
@ -22,8 +22,27 @@ G00Handler::G00Handler() {
|
|||
}
|
||||
|
||||
int G00Handler::execute(Command* command) {
|
||||
|
||||
|
||||
// Serial.print("R99");
|
||||
// Serial.print(" X ");
|
||||
// Serial.print(command->getX());
|
||||
// Serial.print(" Y ");
|
||||
// Serial.print(command->getY());
|
||||
// Serial.print(" Z ");
|
||||
// Serial.print(command->getZ());
|
||||
// Serial.print(" A ");
|
||||
// Serial.print(command->getA());
|
||||
// Serial.print(" B ");
|
||||
// Serial.print(command->getB());
|
||||
// Serial.print(" C ");
|
||||
// Serial.print(command->getC());
|
||||
// Serial.print("\n");
|
||||
|
||||
|
||||
StepperControl::getInstance()->moveAbsoluteConstant(
|
||||
command->getX(), command->getY(), command->getZ(),
|
||||
command->getX(), command->getY(), command->getZ(),
|
||||
//0,0,0,
|
||||
command->getA(), command->getB(), command->getC(),
|
||||
false, false, false);
|
||||
if (LOGGING) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "ServoControl.h"
|
||||
#include "Servo.h"
|
||||
#include "TimerOne.h"
|
||||
|
||||
/*
|
||||
Servo pin layout
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "StepperControl.h"
|
||||
#include "TimerOne.h"
|
||||
|
||||
static StepperControl* instance;
|
||||
|
||||
|
@ -10,7 +11,55 @@ StepperControl * StepperControl::getInstance() {
|
|||
}
|
||||
;
|
||||
|
||||
const int MOVEMENT_INTERRUPT_SPEED = 100; // Interrupt cycle in micro seconds
|
||||
|
||||
int test = 0;
|
||||
|
||||
long sourcePoint[3] = {0,0,0};
|
||||
long currentPoint[3] = {0,0,0};
|
||||
long destinationPoint[3] = {0,0,0};
|
||||
unsigned long movementLength[3] = {0,0,0};
|
||||
unsigned long maxLenth = 0;
|
||||
unsigned long moveTicks[3] = {0,0,0};
|
||||
unsigned long stepOnTick[3] = {0,0,0};
|
||||
unsigned long stepOffTick[3] = {0,0,0};
|
||||
unsigned long axisSpeed[3] = {0,0,0};
|
||||
double lengthRatio[3] = {0,0,0};
|
||||
long speedMax[3] = {0,0,0};
|
||||
long speedMin[3] = {0,0,0};
|
||||
long stepsAcc[3] = {0,0,0};
|
||||
long timeOut[3] = {0,0,0};
|
||||
bool homeIsUp[3] = {false,false,false};
|
||||
bool motorInv[3] = {false,false,false};
|
||||
bool endStInv[3] = {false,false,false};
|
||||
bool homeAxis[3] = {false,false,false};
|
||||
bool axisActive[3] = {false,false,false};
|
||||
bool movementUp[3] = {false,false,false};
|
||||
bool movementToHome[3] = {false,false,false};
|
||||
bool home = false;
|
||||
|
||||
|
||||
// ** test code
|
||||
|
||||
// The interrupt will blink the LED, and keep
|
||||
// track of how many times it has blinked.
|
||||
int ledState = LOW;
|
||||
//volatile unsigned long blinkCount = 0; // use volatile for shared variables
|
||||
|
||||
void blinkLed() {
|
||||
if (ledState == LOW) {
|
||||
ledState = HIGH;
|
||||
//Serial.print("R99 led on");
|
||||
} else {
|
||||
ledState = LOW;
|
||||
//Serial.print("R99 led off");
|
||||
}
|
||||
digitalWrite(LED_PIN, ledState);
|
||||
}
|
||||
|
||||
|
||||
StepperControl::StepperControl() {
|
||||
|
||||
}
|
||||
|
||||
unsigned long getMaxLength(unsigned long lengths[3]) {
|
||||
|
@ -121,6 +170,21 @@ void step(int axis, long ¤tPoint, unsigned long steps,
|
|||
}
|
||||
}
|
||||
|
||||
void resetStep(int axis) {
|
||||
switch (axis) {
|
||||
case 0:
|
||||
digitalWrite(X_STEP_PIN, LOW);
|
||||
break;
|
||||
case 1:
|
||||
digitalWrite(Y_STEP_PIN, LOW);
|
||||
break;
|
||||
case 2:
|
||||
digitalWrite(Z_STEP_PIN, LOW);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool pointReached(long currentPoint[3],
|
||||
long destinationPoint[3]) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
|
@ -166,6 +230,9 @@ unsigned int calculateSpeed(unsigned int ¤tStepsPerSecond,
|
|||
}
|
||||
*/
|
||||
|
||||
|
||||
unsigned int lastCalcLog = 0;
|
||||
|
||||
unsigned int calculateSpeed(long sourcePosition, long currentPosition, long destinationPosition, long minSpeed, long maxSpeed, long stepsAccDec) {
|
||||
|
||||
int newSpeed = 0;
|
||||
|
@ -210,42 +277,45 @@ unsigned int calculateSpeed(long sourcePosition, long currentPosition, long dest
|
|||
}
|
||||
}
|
||||
|
||||
if (LOGGING) {
|
||||
if (millis() % 200 == 0 && currentPosition != destinationPosition) {
|
||||
/*
|
||||
if (millis() - lastCalcLog > 1000) {
|
||||
|
||||
Serial.print("R99");
|
||||
lastCalcLog = millis();
|
||||
|
||||
// Serial.print(" a ");
|
||||
// Serial.print(endPos);
|
||||
// Serial.print(" b ");
|
||||
// Serial.print((endPos - stepsAccDec));
|
||||
// Serial.print(" c ");
|
||||
// Serial.print(curPos < (endPos - stepsAccDec));
|
||||
Serial.print("R99");
|
||||
|
||||
// Serial.print(" a ");
|
||||
// Serial.print(endPos);
|
||||
// Serial.print(" b ");
|
||||
// Serial.print((endPos - stepsAccDec));
|
||||
// Serial.print(" c ");
|
||||
// Serial.print(curPos < (endPos - stepsAccDec));
|
||||
|
||||
|
||||
Serial.print(" sta ");
|
||||
Serial.print(staPos);
|
||||
Serial.print(" cur ");
|
||||
Serial.print(curPos);
|
||||
Serial.print(" end ");
|
||||
Serial.print(endPos);
|
||||
Serial.print(" half ");
|
||||
Serial.print(halfway);
|
||||
Serial.print(" len ");
|
||||
Serial.print(stepsAccDec);
|
||||
// Serial.print(" min ");
|
||||
// Serial.print(minSpeed);
|
||||
// Serial.print(" max ");
|
||||
// Serial.print(maxSpeed);
|
||||
Serial.print(" spd ");
|
||||
Serial.print(" sta ");
|
||||
Serial.print(staPos);
|
||||
Serial.print(" cur ");
|
||||
Serial.print(curPos);
|
||||
Serial.print(" end ");
|
||||
Serial.print(endPos);
|
||||
Serial.print(" half ");
|
||||
Serial.print(halfway);
|
||||
Serial.print(" len ");
|
||||
Serial.print(stepsAccDec);
|
||||
Serial.print(" min ");
|
||||
Serial.print(minSpeed);
|
||||
Serial.print(" max ");
|
||||
Serial.print(maxSpeed);
|
||||
Serial.print(" spd ");
|
||||
|
||||
Serial.print(" ");
|
||||
Serial.print(newSpeed);
|
||||
Serial.print(" ");
|
||||
Serial.print(newSpeed);
|
||||
|
||||
Serial.print("\n");
|
||||
}
|
||||
Serial.print("\n");
|
||||
}
|
||||
*/
|
||||
|
||||
// Return the calculated speed, in steps per second
|
||||
return newSpeed;
|
||||
}
|
||||
|
||||
|
@ -335,6 +405,242 @@ void doseWaterByTime(long time) {
|
|||
digitalWrite(HEATER_1_PIN, LOW);
|
||||
}
|
||||
|
||||
void checkAxisDirection(int i) {
|
||||
if (homeAxis[i]){
|
||||
// When home is active, the direction is fixed
|
||||
movementUp[i] = homeIsUp[i];
|
||||
movementToHome[i] = true;
|
||||
} else {
|
||||
// For normal movement, move in direction of destination
|
||||
movementUp[i] = ( currentPoint[i] < destinationPoint[i] );
|
||||
movementToHome[i] = (abs(currentPoint[i]) >= abs(destinationPoint[i]));
|
||||
}
|
||||
|
||||
if (currentPoint[i] == 0) {
|
||||
// Go slow when theoretical end point reached but there is no end stop siganl
|
||||
axisSpeed[i] = speedMin[i];
|
||||
}
|
||||
}
|
||||
|
||||
void stepAxis(int i, bool state) {
|
||||
|
||||
if (homeAxis[i] && currentPoint[i] == 0) {
|
||||
|
||||
// Keep moving toward end stop even when position is zero
|
||||
// but end stop is not yet active
|
||||
if (homeIsUp[i]) {
|
||||
currentPoint[i] = -1;
|
||||
} else {
|
||||
currentPoint[i] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// set a step on the motors
|
||||
step(i, currentPoint[i], 1, destinationPoint[i]);
|
||||
blinkLed();
|
||||
//stepMade = true;
|
||||
//lastStepMillis[i] = currentMillis;
|
||||
|
||||
}
|
||||
|
||||
void checkAxis(int i) {
|
||||
|
||||
//moveTicks[i]++;
|
||||
checkAxisDirection(i);
|
||||
|
||||
|
||||
/*
|
||||
Serial.print("R99 check axis ");
|
||||
Serial.print(i);
|
||||
Serial.print(" axis active ");
|
||||
Serial.print(axisActive[i]);
|
||||
Serial.print(" current point ");
|
||||
Serial.print(currentPoint[i]);
|
||||
Serial.print(" destination point ");
|
||||
Serial.print(destinationPoint[i]);
|
||||
|
||||
Serial.print(" home stop reached ");
|
||||
Serial.print(endStopAxisReached(i, false));
|
||||
Serial.print(" axis stop reached ");
|
||||
Serial.print(endStopAxisReached(i, true));
|
||||
Serial.print(" home axis ");
|
||||
Serial.print(homeAxis[i]);
|
||||
Serial.print(" movement to home ");
|
||||
Serial.print(movementToHome[i]);
|
||||
Serial.print("\n");
|
||||
*/
|
||||
|
||||
|
||||
//if ((!pointReached(currentPoint, destinationPoint) || home) && axisActive[i]) {
|
||||
if (((currentPoint[i] != destinationPoint[i]) || homeAxis[i]) && axisActive[i]) {
|
||||
//Serial.print("R99 point not reached yet\n");
|
||||
// home or destination not reached, keep moving
|
||||
/*
|
||||
Serial.print("R99 calc axis speed");
|
||||
Serial.print(" speed max ");
|
||||
Serial.print(speedMax[i]);
|
||||
Serial.print("\n");
|
||||
*/
|
||||
|
||||
// Get the axis speed, in steps per second
|
||||
axisSpeed[i] = calculateSpeed( sourcePoint[i],currentPoint[i],destinationPoint[i],
|
||||
speedMin[i], speedMax[i], stepsAcc[i]);
|
||||
|
||||
//Serial.print("R99 axis speed ");
|
||||
//Serial.print(axisSpeed[i]);
|
||||
//Serial.print("\n");
|
||||
|
||||
/*
|
||||
Serial.print("R99 check axis b ");
|
||||
Serial.print(i);
|
||||
Serial.print(" home part true ");
|
||||
Serial.print(homeAxis[i] && !endStopAxisReached(i, false));
|
||||
Serial.print(" !homeAxis[i] ");
|
||||
Serial.print(!homeAxis[i]);
|
||||
Serial.print(" !endStopAxisReached(i, !movementToHome[i]) ");
|
||||
Serial.print(!endStopAxisReached(i, !movementToHome[i]));
|
||||
Serial.print("\n");
|
||||
*/
|
||||
// If end stop reached, don't move anymore
|
||||
if ((homeAxis[i] && !endStopAxisReached(i, false)) || (!homeAxis[i] && !endStopAxisReached(i, !movementToHome[i]))) {
|
||||
|
||||
// Set the moments when the step is set to true and false
|
||||
|
||||
if (axisSpeed[i] > 0)
|
||||
{
|
||||
/*
|
||||
Serial.print("R99 calculated steps ");
|
||||
Serial.print(" ** additional ticks steps ");
|
||||
Serial.print(1000.0 * 1000.0 / MOVEMENT_INTERRUPT_SPEED / axisSpeed[i]);
|
||||
Serial.print("\n");
|
||||
*/
|
||||
|
||||
// Take the requested speed (steps / second) and divide by the interrupt speed (interrupts per seconde)
|
||||
// This gives the number of interrupts (called ticks here) before the pulse needs to be set for the next step
|
||||
stepOnTick[i] = moveTicks[i] + (1000.0 * 1000.0 / MOVEMENT_INTERRUPT_SPEED / axisSpeed[i] / 2);
|
||||
stepOffTick[i] = moveTicks[i] + (1000.0 * 1000.0 / MOVEMENT_INTERRUPT_SPEED / axisSpeed[i] );
|
||||
//stepOnTick[i] = moveTicks[i] + (axisSpeed[i] * 1000 / MOVEMENT_INTERRUPT_SPEED / 2);
|
||||
//stepOffTick[i] = moveTicks[i] + (axisSpeed[i] * 1000 / MOVEMENT_INTERRUPT_SPEED );
|
||||
|
||||
/*
|
||||
Serial.print("R99 calculated steps ");
|
||||
Serial.print(" interrupt speed ");
|
||||
Serial.print(MOVEMENT_INTERRUPT_SPEED);
|
||||
Serial.print(" axisSpeed ");
|
||||
Serial.print(axisSpeed[i]);
|
||||
Serial.print(" moveTicks ");
|
||||
Serial.print(moveTicks[i]);
|
||||
Serial.print(" stepOnTick ");
|
||||
Serial.print(stepOnTick[i]);
|
||||
Serial.print(" stepOffTick ");
|
||||
Serial.print(stepOffTick[i]);
|
||||
Serial.print("\n");
|
||||
*/
|
||||
}
|
||||
}
|
||||
else {
|
||||
axisActive[i] = false;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Destination or home reached. Deactivate the axis.
|
||||
axisActive[i] = false;
|
||||
}
|
||||
|
||||
// If end stop for home is active, set the position to zero
|
||||
if (endStopAxisReached(i, false)) {
|
||||
currentPoint[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void checkTicksAxis(int i) {
|
||||
|
||||
moveTicks[i]++;
|
||||
|
||||
//Serial.print("R99 checkTicksAxis ");
|
||||
//Serial.print(" destination point ");
|
||||
//Serial.print(destinationPoint[0]);
|
||||
//Serial.print(" moveTicks ");
|
||||
//Serial.print(moveTicks[i]);
|
||||
//Serial.print(" stepOnTick ");
|
||||
//Serial.print(stepOnTick[i]);
|
||||
//Serial.print(" stepOffTick ");
|
||||
//Serial.print(stepOffTick[i]);
|
||||
//Serial.print("\n");
|
||||
|
||||
if (axisActive[i]) {
|
||||
if (moveTicks[i] >= stepOffTick[i]) {
|
||||
|
||||
/*
|
||||
Serial.print("R99 reset step ");
|
||||
Serial.print(" moveTicks ");
|
||||
Serial.print(moveTicks[i]);
|
||||
Serial.print("\n");
|
||||
*/
|
||||
// Negative flank for the steps
|
||||
resetStep(i);
|
||||
checkAxis(i);
|
||||
}
|
||||
else {
|
||||
|
||||
if (moveTicks[i] == stepOnTick[i]) {
|
||||
/*
|
||||
Serial.print("R99 set step ");
|
||||
Serial.print(" moveTicks ");
|
||||
Serial.print(moveTicks[i]);
|
||||
Serial.print("\n");
|
||||
*/
|
||||
// Positive flank for the steps
|
||||
stepAxis(i, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Handle movement by checking each axis
|
||||
void StepperControl::handleMovementInterrupt(void){
|
||||
//Serial.print("R99 interrupt\n");
|
||||
|
||||
//Serial.print("R99 interrupt data ");
|
||||
//Serial.print(" destination point ");
|
||||
//Serial.print(destinationPoint[0]);
|
||||
//Serial.print(" ");
|
||||
//Serial.print("test ");
|
||||
//Serial.print(test);
|
||||
//Serial.print("\n");
|
||||
|
||||
checkTicksAxis(0);
|
||||
checkTicksAxis(1);
|
||||
checkTicksAxis(2);
|
||||
|
||||
// blinkLed();
|
||||
|
||||
}
|
||||
|
||||
bool interruptBusy = false;
|
||||
void handleMovementInterruptTest(void) {
|
||||
if (interruptBusy == false) {
|
||||
interruptBusy = true;
|
||||
StepperControl::getInstance()->handleMovementInterrupt();
|
||||
//blinkLed();
|
||||
interruptBusy = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Start the interrupt used for moviing
|
||||
// Interrupt management code library written by Paul Stoffregen
|
||||
void StepperControl::initInterrupt() {
|
||||
//Timer1.attachInterrupt(StepperControl::getInstance()->handleMovementInterrupt);
|
||||
Timer1.attachInterrupt(handleMovementInterruptTest);
|
||||
Timer1.initialize(MOVEMENT_INTERRUPT_SPEED);
|
||||
Timer1.stop();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* xDest - destination X in steps
|
||||
* yDest - destination Y in steps
|
||||
|
@ -346,70 +652,92 @@ int StepperControl::moveAbsoluteConstant( long xDest, long yDest, long zDest,
|
|||
unsigned int xMaxSpd, unsigned int yMaxSpd, unsigned int zMaxSpd,
|
||||
bool xHome, bool yHome, bool zHome) {
|
||||
|
||||
long sourcePoint[3] = { CurrentState::getInstance()->getX(),
|
||||
CurrentState::getInstance()->getY(),
|
||||
CurrentState::getInstance()->getZ() };
|
||||
|
||||
long currentPoint[3] = { CurrentState::getInstance()->getX(),
|
||||
CurrentState::getInstance()->getY(),
|
||||
CurrentState::getInstance()->getZ() };
|
||||
//Serial.print("R99 ");
|
||||
//Serial.print(" xMaxSpd ");
|
||||
//Serial.print(xMaxSpd);
|
||||
//Serial.print("\n");
|
||||
|
||||
long destinationPoint[3] = { xDest, yDest, zDest };
|
||||
sourcePoint[0] = CurrentState::getInstance()->getX();
|
||||
sourcePoint[1] = CurrentState::getInstance()->getY();
|
||||
sourcePoint[2] = CurrentState::getInstance()->getZ();
|
||||
|
||||
unsigned long movementLength[3] = { getLength(destinationPoint[0], currentPoint[0]),
|
||||
getLength(destinationPoint[1], currentPoint[1]),
|
||||
getLength(destinationPoint[2], currentPoint[2])};
|
||||
unsigned long maxLenth = getMaxLength(movementLength);
|
||||
currentPoint[0] = CurrentState::getInstance()->getX();
|
||||
currentPoint[1] = CurrentState::getInstance()->getY();
|
||||
currentPoint[2] = CurrentState::getInstance()->getZ();
|
||||
|
||||
double lengthRatio[3] = { 1.0 * movementLength[0] / maxLenth,
|
||||
1.0 * movementLength[1] / maxLenth,
|
||||
1.0 * movementLength[2] / maxLenth };
|
||||
destinationPoint[0] = xDest;
|
||||
destinationPoint[1] = yDest;
|
||||
destinationPoint[2] = zDest;
|
||||
|
||||
bool homeIsUp[3] = { ParameterList::getInstance()->getValue(MOVEMENT_HOME_UP_X),
|
||||
ParameterList::getInstance()->getValue(MOVEMENT_HOME_UP_Y),
|
||||
ParameterList::getInstance()->getValue(MOVEMENT_HOME_UP_Z) };
|
||||
movementLength[0] = getLength(destinationPoint[0], currentPoint[0]);
|
||||
movementLength[1] = getLength(destinationPoint[1], currentPoint[1]);
|
||||
movementLength[2] = getLength(destinationPoint[2], currentPoint[2]);
|
||||
|
||||
long speedMax[3] = { ParameterList::getInstance()->getValue(MOVEMENT_MAX_SPD_X),
|
||||
ParameterList::getInstance()->getValue(MOVEMENT_MAX_SPD_Y),
|
||||
ParameterList::getInstance()->getValue(MOVEMENT_MAX_SPD_Z) };
|
||||
maxLenth = getMaxLength(movementLength);
|
||||
|
||||
long speedMin[3] = { ParameterList::getInstance()->getValue(MOVEMENT_MIN_SPD_X),
|
||||
ParameterList::getInstance()->getValue(MOVEMENT_MIN_SPD_Y),
|
||||
ParameterList::getInstance()->getValue(MOVEMENT_MIN_SPD_Z) };
|
||||
lengthRatio[0] = 1.0 * movementLength[0] / maxLenth;
|
||||
lengthRatio[1] = 1.0 * movementLength[1] / maxLenth;
|
||||
lengthRatio[2] = 1.0 * movementLength[2] / maxLenth;
|
||||
|
||||
long stepsAcc[3] = { ParameterList::getInstance()->getValue(MOVEMENT_STEPS_ACC_DEC_X),
|
||||
ParameterList::getInstance()->getValue(MOVEMENT_STEPS_ACC_DEC_Y),
|
||||
ParameterList::getInstance()->getValue(MOVEMENT_STEPS_ACC_DEC_Z) };
|
||||
homeIsUp[0] = ParameterList::getInstance()->getValue(MOVEMENT_HOME_UP_X);
|
||||
homeIsUp[1] = ParameterList::getInstance()->getValue(MOVEMENT_HOME_UP_Y);
|
||||
homeIsUp[2] = ParameterList::getInstance()->getValue(MOVEMENT_HOME_UP_Z);
|
||||
|
||||
bool motorInv[3] = { ParameterList::getInstance()->getValue(MOVEMENT_INVERT_MOTOR_X),
|
||||
ParameterList::getInstance()->getValue(MOVEMENT_INVERT_MOTOR_Y),
|
||||
ParameterList::getInstance()->getValue(MOVEMENT_INVERT_MOTOR_Z) };
|
||||
speedMax[0] = ParameterList::getInstance()->getValue(MOVEMENT_MAX_SPD_X);
|
||||
speedMax[1] = ParameterList::getInstance()->getValue(MOVEMENT_MAX_SPD_Y);
|
||||
speedMax[2] = ParameterList::getInstance()->getValue(MOVEMENT_MAX_SPD_Z);
|
||||
|
||||
bool endStInv[3] = { ParameterList::getInstance()->getValue(MOVEMENT_INVERT_ENDPOINTS_X),
|
||||
ParameterList::getInstance()->getValue(MOVEMENT_INVERT_ENDPOINTS_Y),
|
||||
ParameterList::getInstance()->getValue(MOVEMENT_INVERT_ENDPOINTS_Z) };
|
||||
speedMin[0] = ParameterList::getInstance()->getValue(MOVEMENT_MIN_SPD_X);
|
||||
speedMin[1] = ParameterList::getInstance()->getValue(MOVEMENT_MIN_SPD_Y);
|
||||
speedMin[2] = ParameterList::getInstance()->getValue(MOVEMENT_MIN_SPD_Z);
|
||||
|
||||
long timeOut[3] = { ParameterList::getInstance()->getValue(MOVEMENT_TIMEOUT_X),
|
||||
ParameterList::getInstance()->getValue(MOVEMENT_TIMEOUT_X),
|
||||
ParameterList::getInstance()->getValue(MOVEMENT_TIMEOUT_X) };
|
||||
stepsAcc[0] = ParameterList::getInstance()->getValue(MOVEMENT_STEPS_ACC_DEC_X);
|
||||
stepsAcc[1] = ParameterList::getInstance()->getValue(MOVEMENT_STEPS_ACC_DEC_Y);
|
||||
stepsAcc[2] = ParameterList::getInstance()->getValue(MOVEMENT_STEPS_ACC_DEC_Z);
|
||||
|
||||
motorInv[0] = ParameterList::getInstance()->getValue(MOVEMENT_INVERT_MOTOR_X);
|
||||
motorInv[1] = ParameterList::getInstance()->getValue(MOVEMENT_INVERT_MOTOR_Y);
|
||||
motorInv[2] = ParameterList::getInstance()->getValue(MOVEMENT_INVERT_MOTOR_Z);
|
||||
|
||||
endStInv[0] = ParameterList::getInstance()->getValue(MOVEMENT_INVERT_ENDPOINTS_X);
|
||||
endStInv[1] = ParameterList::getInstance()->getValue(MOVEMENT_INVERT_ENDPOINTS_Y);
|
||||
endStInv[2] = ParameterList::getInstance()->getValue(MOVEMENT_INVERT_ENDPOINTS_Z);
|
||||
|
||||
timeOut[0] = ParameterList::getInstance()->getValue(MOVEMENT_TIMEOUT_X);
|
||||
timeOut[1] = ParameterList::getInstance()->getValue(MOVEMENT_TIMEOUT_X);
|
||||
timeOut[2] = ParameterList::getInstance()->getValue(MOVEMENT_TIMEOUT_X);
|
||||
|
||||
homeAxis[0] = xHome;
|
||||
homeAxis[1] = yHome;
|
||||
homeAxis[2] = zHome;
|
||||
|
||||
moveTicks[0] = 0;
|
||||
moveTicks[1] = 0;
|
||||
moveTicks[2] = 0;
|
||||
|
||||
home = xHome || yHome || zHome;
|
||||
|
||||
//Serial.print("R99 ");
|
||||
//Serial.print(" after vars ");
|
||||
//Serial.print(destinationPoint[0]);
|
||||
//Serial.print("\n");
|
||||
|
||||
bool homeAxis[3] = { xHome, yHome, zHome };
|
||||
bool home = xHome || yHome || zHome;
|
||||
|
||||
unsigned long currentMillis = 0;
|
||||
|
||||
unsigned long currentSteps = 0;
|
||||
unsigned long lastStepMillis[3] = { 0, 0, 0 };
|
||||
|
||||
unsigned long timeStart = millis();
|
||||
|
||||
|
||||
bool movementDone = false;
|
||||
bool movementUp = false;
|
||||
bool movementToHome = false;
|
||||
|
||||
bool moving = false;
|
||||
|
||||
bool stepMade = false;
|
||||
int incomingByte = 0;
|
||||
int axisSpeed = 0;
|
||||
//int axisSpeed = 0;
|
||||
int error = 0;
|
||||
|
||||
// if a speed is given in the command, use that instead of the config speed
|
||||
|
@ -428,13 +756,13 @@ int StepperControl::moveAbsoluteConstant( long xDest, long yDest, long zDest,
|
|||
|
||||
// Prepare for movement
|
||||
|
||||
setDirections(currentPoint, destinationPoint, homeAxis, motorInv);
|
||||
|
||||
|
||||
storeEndStops();
|
||||
reportEndStops();
|
||||
enableMotors(true);
|
||||
|
||||
setDirections(currentPoint, destinationPoint, homeAxis, motorInv);
|
||||
|
||||
|
||||
// Limit normal movmement to the home position
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (!homeIsUp[i] && destinationPoint[i] < 0) {
|
||||
|
@ -448,109 +776,92 @@ int StepperControl::moveAbsoluteConstant( long xDest, long yDest, long zDest,
|
|||
|
||||
// Start movement
|
||||
|
||||
while (!movementDone) {
|
||||
axisActive[0] = true;
|
||||
axisActive[1] = true;
|
||||
axisActive[2] = true;
|
||||
|
||||
checkAxis(0);
|
||||
checkAxis(1);
|
||||
checkAxis(2);
|
||||
|
||||
Timer1.start();
|
||||
|
||||
|
||||
// Let the interrupt handle all the movements
|
||||
while (axisActive[0] || axisActive[1] || axisActive[2]) {
|
||||
/**///Serial.print("R99 while loop\n");
|
||||
//delay(50);
|
||||
delayMicroseconds(100);
|
||||
|
||||
//Serial.print("R99 ");
|
||||
//Serial.print(" maximim speed ");
|
||||
//Serial.print(speedMax[0]);
|
||||
//Serial.print("\n");
|
||||
|
||||
|
||||
checkTicksAxis(0);
|
||||
checkTicksAxis(1);
|
||||
checkTicksAxis(2);
|
||||
|
||||
|
||||
//axisActive[0] = false;
|
||||
//axisActive[1] = false;
|
||||
//axisActive[2] = false;
|
||||
|
||||
/*
|
||||
Serial.print("R99");
|
||||
Serial.print(" cur ");
|
||||
Serial.print(currentPoint[0]);
|
||||
Serial.print(" end ");
|
||||
Serial.print(destinationPoint[0]);
|
||||
Serial.print(" max spd ");
|
||||
Serial.print(speedMax[0]);
|
||||
Serial.print(" axis spd ");
|
||||
Serial.print(axisSpeed[0]);
|
||||
Serial.print("\n");
|
||||
*/
|
||||
|
||||
storeEndStops();
|
||||
|
||||
// Check timeouts
|
||||
if (axisActive[0] == true && ((millis() >= timeStart && millis() - timeStart > timeOut[0] * 1000) || (millis() < timeStart && millis() > timeOut[0] * 1000))) {
|
||||
error = 1;
|
||||
}
|
||||
if (axisActive[1] == true && ((millis() >= timeStart && millis() - timeStart > timeOut[0] * 1000) || (millis() < timeStart && millis() > timeOut[0] * 1000))) {
|
||||
error = 1;
|
||||
}
|
||||
if (axisActive[2] == true && ((millis() >= timeStart && millis() - timeStart > timeOut[0] * 1000) || (millis() < timeStart && millis() > timeOut[0] * 1000))) {
|
||||
error = 1;
|
||||
}
|
||||
|
||||
// Check if there is an emergency stop command
|
||||
if (Serial.available() > 0) {
|
||||
incomingByte = Serial.read();
|
||||
if (incomingByte == 69 || incomingByte == 101) {
|
||||
movementDone = true;
|
||||
}
|
||||
error = 1;
|
||||
}
|
||||
}
|
||||
|
||||
stepMade = false;
|
||||
moving = false;
|
||||
|
||||
// Keep moving until destination reached or while moving home and end stop not reached
|
||||
if ((!pointReached(currentPoint, destinationPoint) || home) && !movementDone) {
|
||||
|
||||
// Check each axis
|
||||
for (int i = 0; i < 3; i++) {
|
||||
|
||||
axisSpeed = calculateSpeed( sourcePoint[i],currentPoint[i],destinationPoint[i],
|
||||
speedMin[i], speedMax[i], stepsAcc[i]);
|
||||
|
||||
if (homeAxis[i]){
|
||||
// When home is active, the direction is fixed
|
||||
movementUp = homeIsUp[i];
|
||||
movementToHome = true;
|
||||
if (currentPoint[i] == 0) {
|
||||
// Go slow when theoretical end point reached but there is no end stop siganl
|
||||
axisSpeed = speedMin[i];
|
||||
}
|
||||
} else {
|
||||
// For normal movement, move in direction of destination
|
||||
movementUp = ( currentPoint[i] < destinationPoint[i] );
|
||||
movementToHome = (abs(currentPoint[i]) >= abs(destinationPoint[i]));
|
||||
}
|
||||
|
||||
if (millis() - timeStart > timeOut[i] * MOVEMENT_SPEED_BASE_TIME) {
|
||||
error = 1;
|
||||
} else {
|
||||
|
||||
//if ()
|
||||
// If end stop reached, don't move anymore
|
||||
if ((homeAxis[i] && !endStopAxisReached(i, false)) || (!homeAxis[i] && !endStopAxisReached(i, !movementToHome) && currentPoint[i] != destinationPoint[i] )) {
|
||||
moving = true;
|
||||
|
||||
// Only do a step every x milliseconds (x is calculated above)
|
||||
if (currentMillis - lastStepMillis[i] >= MOVEMENT_SPEED_BASE_TIME / axisSpeed) {
|
||||
|
||||
if (homeAxis[i] && currentPoint[i] == 0) {
|
||||
// Keep moving toward end stop even when position is zero
|
||||
// but end stop is not yet active
|
||||
if (homeIsUp[i]) {
|
||||
currentPoint[i] = -1;
|
||||
} else {
|
||||
currentPoint[i] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// set a step on the motors
|
||||
step(i, currentPoint[i], 1, destinationPoint[i]);
|
||||
stepMade = true;
|
||||
lastStepMillis[i] = currentMillis;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// If end stop for home is active, set the position to zero
|
||||
if (endStopAxisReached(i, false))
|
||||
{
|
||||
currentPoint[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
movementDone = true;
|
||||
}
|
||||
delayMicroseconds(MOVEMENT_DELAY);
|
||||
if (stepMade) {
|
||||
currentSteps++;
|
||||
if (error == 1) {
|
||||
Serial.print("R99 error\n");
|
||||
Timer1.stop();
|
||||
axisActive[0] = false;
|
||||
axisActive[1] = false;
|
||||
axisActive[2] = false;
|
||||
}
|
||||
|
||||
// Periodically send message still active
|
||||
currentMillis++;
|
||||
if (currentMillis % 10000 == 0)
|
||||
if (currentMillis % 2500 == 0)
|
||||
{
|
||||
// Periodically send message still active
|
||||
Serial.print("R04\n");
|
||||
}
|
||||
|
||||
if (stepMade) {
|
||||
digitalWrite(X_STEP_PIN, LOW);
|
||||
digitalWrite(Y_STEP_PIN, LOW);
|
||||
digitalWrite(Z_STEP_PIN, LOW);
|
||||
}
|
||||
if (!moving)
|
||||
{
|
||||
movementDone = true;
|
||||
}
|
||||
|
||||
delayMicroseconds(MOVEMENT_DELAY);
|
||||
}
|
||||
|
||||
/**/Serial.print("R99 stopped\n");
|
||||
|
||||
Timer1.stop();
|
||||
enableMotors(false);
|
||||
|
||||
CurrentState::getInstance()->setX(currentPoint[0]);
|
||||
|
@ -614,8 +925,8 @@ int StepperControl::calibrateAxis(int axis) {
|
|||
int paramValueInt = 0;
|
||||
bool invertEndStops = false;
|
||||
int stepsCount = 0;
|
||||
int incomingByte = 0;
|
||||
int error = 0;
|
||||
int incomingByte = 0;
|
||||
int error = 0;
|
||||
|
||||
|
||||
// Prepare for movement
|
||||
|
@ -661,7 +972,7 @@ Serial.print("\n");
|
|||
// Move until the end stop for home position is reached
|
||||
if ((!endStopMin(axis) && !endStopMax(axis)) && !movementDone) {
|
||||
|
||||
if (millis() - timeStart > timeOut[axis] * MOVEMENT_SPEED_BASE_TIME) {
|
||||
if ((millis() >= timeStart && millis() - timeStart > timeOut[axis] * 1000) || (millis() < timeStart && millis() > timeOut[axis] * 1000)) {
|
||||
movementDone = true;
|
||||
error = 1;
|
||||
} else {
|
||||
|
@ -845,3 +1156,4 @@ Serial.print("\n");
|
|||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,10 @@ public:
|
|||
int moveAbsoluteConstant(long xDest, long yDest, long zDest,
|
||||
unsigned int xMaxSpd, unsigned int yMaxSpd, unsigned int zMaxSpd,
|
||||
bool homeX, bool homeY, bool homeZ);
|
||||
|
||||
void handleMovementInterrupt();
|
||||
int calibrateAxis(int axis);
|
||||
void initInterrupt();
|
||||
private:
|
||||
StepperControl();
|
||||
StepperControl(StepperControl const&);
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Interrupt and PWM utilities for 16 bit Timer1 on ATmega168/328
|
||||
* Original code by Jesse Tane for http://labs.ideo.com August 2008
|
||||
* Modified March 2009 by Jérôme Despatis and Jesse Tane for ATmega328 support
|
||||
* Modified June 2009 by Michael Polli and Jesse Tane to fix a bug in setPeriod() which caused the timer to stop
|
||||
* Modified Oct 2009 by Dan Clemens to work with timer1 of the ATMega1280 or Arduino Mega
|
||||
* Modified April 2012 by Paul Stoffregen
|
||||
* Modified again, June 2014 by Paul Stoffregen
|
||||
*
|
||||
* This is free software. You can redistribute it and/or modify it under
|
||||
* the terms of Creative Commons Attribution 3.0 United States License.
|
||||
* To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/us/
|
||||
* or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "TimerOne.h"
|
||||
|
||||
TimerOne Timer1; // preinstatiate
|
||||
|
||||
unsigned short TimerOne::pwmPeriod = 0;
|
||||
unsigned char TimerOne::clockSelectBits = 0;
|
||||
void (*TimerOne::isrCallback)() = NULL;
|
||||
|
||||
// interrupt service routine that wraps a user defined function supplied by attachInterrupt
|
||||
#if defined(__AVR__)
|
||||
ISR(TIMER1_OVF_vect)
|
||||
{
|
||||
Timer1.isrCallback();
|
||||
}
|
||||
|
||||
#elif defined(__arm__) && defined(CORE_TEENSY)
|
||||
void ftm1_isr(void)
|
||||
{
|
||||
uint32_t sc = FTM1_SC;
|
||||
#ifdef KINETISL
|
||||
if (sc & 0x80) FTM1_SC = sc;
|
||||
#else
|
||||
if (sc & 0x80) FTM1_SC = sc & 0x7F;
|
||||
#endif
|
||||
Timer1.isrCallback();
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,304 @@
|
|||
/*
|
||||
* Interrupt and PWM utilities for 16 bit Timer1 on ATmega168/328
|
||||
* Original code by Jesse Tane for http://labs.ideo.com August 2008
|
||||
* Modified March 2009 by Jérôme Despatis and Jesse Tane for ATmega328 support
|
||||
* Modified June 2009 by Michael Polli and Jesse Tane to fix a bug in setPeriod() which caused the timer to stop
|
||||
* Modified April 2012 by Paul Stoffregen - portable to other AVR chips, use inline functions
|
||||
* Modified again, June 2014 by Paul Stoffregen - support Teensy 3.x & even more AVR chips
|
||||
*
|
||||
*
|
||||
* This is free software. You can redistribute it and/or modify it under
|
||||
* the terms of Creative Commons Attribution 3.0 United States License.
|
||||
* To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/us/
|
||||
* or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TimerOne_h_
|
||||
#define TimerOne_h_
|
||||
|
||||
#if defined(ARDUINO) && ARDUINO >= 100
|
||||
#include "Arduino.h"
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
|
||||
#include "config/known_16bit_timers.h"
|
||||
|
||||
#define TIMER1_RESOLUTION 65536UL // Timer1 is 16 bit
|
||||
|
||||
|
||||
// Placing nearly all the code in this .h file allows the functions to be
|
||||
// inlined by the compiler. In the very common case with constant values
|
||||
// the compiler will perform all calculations and simply write constants
|
||||
// to the hardware registers (for example, setPeriod).
|
||||
|
||||
|
||||
class TimerOne
|
||||
{
|
||||
|
||||
|
||||
#if defined(__AVR__)
|
||||
public:
|
||||
//****************************
|
||||
// Configuration
|
||||
//****************************
|
||||
void initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) {
|
||||
TCCR1B = _BV(WGM13); // set mode as phase and frequency correct pwm, stop the timer
|
||||
TCCR1A = 0; // clear control register A
|
||||
setPeriod(microseconds);
|
||||
}
|
||||
void setPeriod(unsigned long microseconds) __attribute__((always_inline)) {
|
||||
const unsigned long cycles = (F_CPU / 2000000) * microseconds;
|
||||
if (cycles < TIMER1_RESOLUTION) {
|
||||
clockSelectBits = _BV(CS10);
|
||||
pwmPeriod = cycles;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 8) {
|
||||
clockSelectBits = _BV(CS11);
|
||||
pwmPeriod = cycles / 8;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 64) {
|
||||
clockSelectBits = _BV(CS11) | _BV(CS10);
|
||||
pwmPeriod = cycles / 64;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 256) {
|
||||
clockSelectBits = _BV(CS12);
|
||||
pwmPeriod = cycles / 256;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 1024) {
|
||||
clockSelectBits = _BV(CS12) | _BV(CS10);
|
||||
pwmPeriod = cycles / 1024;
|
||||
} else {
|
||||
clockSelectBits = _BV(CS12) | _BV(CS10);
|
||||
pwmPeriod = TIMER1_RESOLUTION - 1;
|
||||
}
|
||||
ICR1 = pwmPeriod;
|
||||
TCCR1B = _BV(WGM13) | clockSelectBits;
|
||||
}
|
||||
|
||||
//****************************
|
||||
// Run Control
|
||||
//****************************
|
||||
void start() __attribute__((always_inline)) {
|
||||
TCCR1B = 0;
|
||||
TCNT1 = 0; // TODO: does this cause an undesired interrupt?
|
||||
resume();
|
||||
}
|
||||
void stop() __attribute__((always_inline)) {
|
||||
TCCR1B = _BV(WGM13);
|
||||
}
|
||||
void restart() __attribute__((always_inline)) {
|
||||
start();
|
||||
}
|
||||
void resume() __attribute__((always_inline)) {
|
||||
TCCR1B = _BV(WGM13) | clockSelectBits;
|
||||
}
|
||||
|
||||
//****************************
|
||||
// PWM outputs
|
||||
//****************************
|
||||
void setPwmDuty(char pin, unsigned int duty) __attribute__((always_inline)) {
|
||||
unsigned long dutyCycle = pwmPeriod;
|
||||
dutyCycle *= duty;
|
||||
dutyCycle >>= 10;
|
||||
if (pin == TIMER1_A_PIN) OCR1A = dutyCycle;
|
||||
#ifdef TIMER1_B_PIN
|
||||
else if (pin == TIMER1_B_PIN) OCR1B = dutyCycle;
|
||||
#endif
|
||||
#ifdef TIMER1_C_PIN
|
||||
else if (pin == TIMER1_C_PIN) OCR1C = dutyCycle;
|
||||
#endif
|
||||
}
|
||||
void pwm(char pin, unsigned int duty) __attribute__((always_inline)) {
|
||||
if (pin == TIMER1_A_PIN) { pinMode(TIMER1_A_PIN, OUTPUT); TCCR1A |= _BV(COM1A1); }
|
||||
#ifdef TIMER1_B_PIN
|
||||
else if (pin == TIMER1_B_PIN) { pinMode(TIMER1_B_PIN, OUTPUT); TCCR1A |= _BV(COM1B1); }
|
||||
#endif
|
||||
#ifdef TIMER1_C_PIN
|
||||
else if (pin == TIMER1_C_PIN) { pinMode(TIMER1_C_PIN, OUTPUT); TCCR1A |= _BV(COM1C1); }
|
||||
#endif
|
||||
setPwmDuty(pin, duty);
|
||||
TCCR1B = _BV(WGM13) | clockSelectBits;
|
||||
}
|
||||
void pwm(char pin, unsigned int duty, unsigned long microseconds) __attribute__((always_inline)) {
|
||||
if (microseconds > 0) setPeriod(microseconds);
|
||||
pwm(pin, duty);
|
||||
}
|
||||
void disablePwm(char pin) __attribute__((always_inline)) {
|
||||
if (pin == TIMER1_A_PIN) TCCR1A &= ~_BV(COM1A1);
|
||||
#ifdef TIMER1_B_PIN
|
||||
else if (pin == TIMER1_B_PIN) TCCR1A &= ~_BV(COM1B1);
|
||||
#endif
|
||||
#ifdef TIMER1_C_PIN
|
||||
else if (pin == TIMER1_C_PIN) TCCR1A &= ~_BV(COM1C1);
|
||||
#endif
|
||||
}
|
||||
|
||||
//****************************
|
||||
// Interrupt Function
|
||||
//****************************
|
||||
void attachInterrupt(void (*isr)()) __attribute__((always_inline)) {
|
||||
isrCallback = isr;
|
||||
TIMSK1 = _BV(TOIE1);
|
||||
}
|
||||
void attachInterrupt(void (*isr)(), unsigned long microseconds) __attribute__((always_inline)) {
|
||||
if(microseconds > 0) setPeriod(microseconds);
|
||||
attachInterrupt(isr);
|
||||
}
|
||||
void detachInterrupt() __attribute__((always_inline)) {
|
||||
TIMSK1 = 0;
|
||||
}
|
||||
static void (*isrCallback)();
|
||||
|
||||
private:
|
||||
// properties
|
||||
static unsigned short pwmPeriod;
|
||||
static unsigned char clockSelectBits;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#elif defined(__arm__) && defined(CORE_TEENSY)
|
||||
|
||||
#if defined(KINETISK)
|
||||
#define F_TIMER F_BUS
|
||||
#elif defined(KINETISL)
|
||||
#define F_TIMER (F_PLL/2)
|
||||
#endif
|
||||
|
||||
public:
|
||||
//****************************
|
||||
// Configuration
|
||||
//****************************
|
||||
void initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) {
|
||||
setPeriod(microseconds);
|
||||
}
|
||||
void setPeriod(unsigned long microseconds) __attribute__((always_inline)) {
|
||||
const unsigned long cycles = (F_TIMER / 2000000) * microseconds;
|
||||
if (cycles < TIMER1_RESOLUTION) {
|
||||
clockSelectBits = 0;
|
||||
pwmPeriod = cycles;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 2) {
|
||||
clockSelectBits = 1;
|
||||
pwmPeriod = cycles >> 1;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 4) {
|
||||
clockSelectBits = 2;
|
||||
pwmPeriod = cycles >> 2;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 8) {
|
||||
clockSelectBits = 3;
|
||||
pwmPeriod = cycles >> 3;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 16) {
|
||||
clockSelectBits = 4;
|
||||
pwmPeriod = cycles >> 4;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 32) {
|
||||
clockSelectBits = 5;
|
||||
pwmPeriod = cycles >> 5;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 64) {
|
||||
clockSelectBits = 6;
|
||||
pwmPeriod = cycles >> 6;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 128) {
|
||||
clockSelectBits = 7;
|
||||
pwmPeriod = cycles >> 7;
|
||||
} else {
|
||||
clockSelectBits = 7;
|
||||
pwmPeriod = TIMER1_RESOLUTION - 1;
|
||||
}
|
||||
uint32_t sc = FTM1_SC;
|
||||
FTM1_SC = 0;
|
||||
FTM1_MOD = pwmPeriod;
|
||||
FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_CPWMS | clockSelectBits | (sc & FTM_SC_TOIE);
|
||||
}
|
||||
|
||||
//****************************
|
||||
// Run Control
|
||||
//****************************
|
||||
void start() __attribute__((always_inline)) {
|
||||
stop();
|
||||
FTM1_CNT = 0;
|
||||
resume();
|
||||
}
|
||||
void stop() __attribute__((always_inline)) {
|
||||
FTM1_SC = FTM1_SC & (FTM_SC_TOIE | FTM_SC_CPWMS | FTM_SC_PS(7));
|
||||
}
|
||||
void restart() __attribute__((always_inline)) {
|
||||
start();
|
||||
}
|
||||
void resume() __attribute__((always_inline)) {
|
||||
FTM1_SC = (FTM1_SC & (FTM_SC_TOIE | FTM_SC_PS(7))) | FTM_SC_CPWMS | FTM_SC_CLKS(1);
|
||||
}
|
||||
|
||||
//****************************
|
||||
// PWM outputs
|
||||
//****************************
|
||||
void setPwmDuty(char pin, unsigned int duty) __attribute__((always_inline)) {
|
||||
unsigned long dutyCycle = pwmPeriod;
|
||||
dutyCycle *= duty;
|
||||
dutyCycle >>= 10;
|
||||
if (pin == TIMER1_A_PIN) {
|
||||
FTM1_C0V = dutyCycle;
|
||||
} else if (pin == TIMER1_B_PIN) {
|
||||
FTM1_C1V = dutyCycle;
|
||||
}
|
||||
}
|
||||
void pwm(char pin, unsigned int duty) __attribute__((always_inline)) {
|
||||
setPwmDuty(pin, duty);
|
||||
if (pin == TIMER1_A_PIN) {
|
||||
*portConfigRegister(TIMER1_A_PIN) = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
|
||||
} else if (pin == TIMER1_B_PIN) {
|
||||
*portConfigRegister(TIMER1_B_PIN) = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
|
||||
}
|
||||
}
|
||||
void pwm(char pin, unsigned int duty, unsigned long microseconds) __attribute__((always_inline)) {
|
||||
if (microseconds > 0) setPeriod(microseconds);
|
||||
pwm(pin, duty);
|
||||
}
|
||||
void disablePwm(char pin) __attribute__((always_inline)) {
|
||||
if (pin == TIMER1_A_PIN) {
|
||||
*portConfigRegister(TIMER1_A_PIN) = 0;
|
||||
} else if (pin == TIMER1_B_PIN) {
|
||||
*portConfigRegister(TIMER1_B_PIN) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//****************************
|
||||
// Interrupt Function
|
||||
//****************************
|
||||
void attachInterrupt(void (*isr)()) __attribute__((always_inline)) {
|
||||
isrCallback = isr;
|
||||
FTM1_SC |= FTM_SC_TOIE;
|
||||
NVIC_ENABLE_IRQ(IRQ_FTM1);
|
||||
}
|
||||
void attachInterrupt(void (*isr)(), unsigned long microseconds) __attribute__((always_inline)) {
|
||||
if(microseconds > 0) setPeriod(microseconds);
|
||||
attachInterrupt(isr);
|
||||
}
|
||||
void detachInterrupt() __attribute__((always_inline)) {
|
||||
FTM1_SC &= ~FTM_SC_TOIE;
|
||||
NVIC_DISABLE_IRQ(IRQ_FTM1);
|
||||
}
|
||||
static void (*isrCallback)();
|
||||
|
||||
private:
|
||||
// properties
|
||||
static unsigned short pwmPeriod;
|
||||
static unsigned char clockSelectBits;
|
||||
|
||||
#undef F_TIMER
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
extern TimerOne Timer1;
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
#ifndef known_16bit_timers_header_
|
||||
#define known_16bit_timers_header_
|
||||
|
||||
// Wiring-S
|
||||
//
|
||||
#if defined(__AVR_ATmega644P__) && defined(WIRING)
|
||||
#define TIMER1_A_PIN 5
|
||||
#define TIMER1_B_PIN 4
|
||||
#define TIMER1_ICP_PIN 6
|
||||
|
||||
// Teensy 2.0
|
||||
//
|
||||
#elif defined(__AVR_ATmega32U4__) && defined(CORE_TEENSY)
|
||||
#define TIMER1_A_PIN 14
|
||||
#define TIMER1_B_PIN 15
|
||||
#define TIMER1_C_PIN 4
|
||||
#define TIMER1_ICP_PIN 22
|
||||
#define TIMER1_CLK_PIN 11
|
||||
#define TIMER3_A_PIN 9
|
||||
#define TIMER3_ICP_PIN 10
|
||||
|
||||
// Teensy++ 2.0
|
||||
#elif defined(__AVR_AT90USB1286__) && defined(CORE_TEENSY)
|
||||
#define TIMER1_A_PIN 25
|
||||
#define TIMER1_B_PIN 26
|
||||
#define TIMER1_C_PIN 27
|
||||
#define TIMER1_ICP_PIN 4
|
||||
#define TIMER1_CLK_PIN 6
|
||||
#define TIMER3_A_PIN 16
|
||||
#define TIMER3_B_PIN 15
|
||||
#define TIMER3_C_PIN 14
|
||||
#define TIMER3_ICP_PIN 17
|
||||
#define TIMER3_CLK_PIN 13
|
||||
|
||||
// Teensy 3.0
|
||||
//
|
||||
#elif defined(__MK20DX128__)
|
||||
#define TIMER1_A_PIN 3
|
||||
#define TIMER1_B_PIN 4
|
||||
#define TIMER1_ICP_PIN 4
|
||||
|
||||
// Teensy 3.1
|
||||
//
|
||||
#elif defined(__MK20DX256__)
|
||||
#define TIMER1_A_PIN 3
|
||||
#define TIMER1_B_PIN 4
|
||||
#define TIMER1_ICP_PIN 4
|
||||
#define TIMER3_A_PIN 32
|
||||
#define TIMER3_B_PIN 25
|
||||
#define TIMER3_ICP_PIN 32
|
||||
|
||||
// Teensy-LC
|
||||
//
|
||||
#elif defined(__MKL26Z64__)
|
||||
#define TIMER1_A_PIN 16
|
||||
#define TIMER1_B_PIN 17
|
||||
#define TIMER1_ICP_PIN 17
|
||||
#define TIMER3_A_PIN 3
|
||||
#define TIMER3_B_PIN 4
|
||||
#define TIMER3_ICP_PIN 4
|
||||
|
||||
// Arduino Mega
|
||||
//
|
||||
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||
#define TIMER1_A_PIN 11
|
||||
#define TIMER1_B_PIN 12
|
||||
#define TIMER1_C_PIN 13
|
||||
#define TIMER3_A_PIN 5
|
||||
#define TIMER3_B_PIN 2
|
||||
#define TIMER3_C_PIN 3
|
||||
#define TIMER4_A_PIN 6
|
||||
#define TIMER4_B_PIN 7
|
||||
#define TIMER4_C_PIN 8
|
||||
#define TIMER4_ICP_PIN 49
|
||||
#define TIMER5_A_PIN 46
|
||||
#define TIMER5_B_PIN 45
|
||||
#define TIMER5_C_PIN 44
|
||||
#define TIMER3_ICP_PIN 48
|
||||
#define TIMER3_CLK_PIN 47
|
||||
|
||||
// Arduino Leonardo, Yun, etc
|
||||
//
|
||||
#elif defined(__AVR_ATmega32U4__)
|
||||
#define TIMER1_A_PIN 9
|
||||
#define TIMER1_B_PIN 10
|
||||
#define TIMER1_C_PIN 11
|
||||
#define TIMER1_ICP_PIN 4
|
||||
#define TIMER1_CLK_PIN 12
|
||||
#define TIMER3_A_PIN 5
|
||||
#define TIMER3_ICP_PIN 13
|
||||
|
||||
// Uno, Duemilanove, LilyPad, etc
|
||||
//
|
||||
#elif defined (__AVR_ATmega168__) || defined (__AVR_ATmega328P__)
|
||||
#define TIMER1_A_PIN 9
|
||||
#define TIMER1_B_PIN 10
|
||||
#define TIMER1_ICP_PIN 8
|
||||
#define TIMER1_CLK_PIN 5
|
||||
|
||||
// Sanguino
|
||||
//
|
||||
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
|
||||
#define TIMER1_A_PIN 13
|
||||
#define TIMER1_B_PIN 12
|
||||
#define TIMER1_ICP_PIN 14
|
||||
#define TIMER1_CLK_PIN 1
|
||||
|
||||
// Wildfire - Wicked Devices
|
||||
//
|
||||
#elif defined(__AVR_ATmega1284P__) && defined(WILDFIRE_VERSION) && WILDFIRE_VERSION >= 3
|
||||
#define TIMER1_A_PIN 5 // PD5
|
||||
#define TIMER1_B_PIN 8 // PD4
|
||||
#define TIMER1_ICP_PIN 6 // PD6
|
||||
#define TIMER1_CLK_PIN 23 // PB1
|
||||
#define TIMER3_A_PIN 12 // PB6
|
||||
#define TIMER3_B_PIN 13 // PB7
|
||||
#define TIMER3_ICP_PIN 9 // PB5
|
||||
#define TIMER3_CLK_PIN 0 // PD0
|
||||
#elif defined(__AVR_ATmega1284P__) && defined(WILDFIRE_VERSION) && WILDFIRE_VERSION < 3
|
||||
#define TIMER1_A_PIN 5 // PD5
|
||||
#define TIMER1_B_PIN 4 // PD4
|
||||
#define TIMER1_ICP_PIN 6 // PD6
|
||||
#define TIMER1_CLK_PIN 15 // PB1
|
||||
#define TIMER3_A_PIN 12 // PB6
|
||||
#define TIMER3_B_PIN 13 // PB7
|
||||
#define TIMER3_ICP_PIN 11 // PB5
|
||||
#define TIMER3_CLK_PIN 0 // PD0
|
||||
|
||||
// Mighty-1284 - Maniacbug
|
||||
//
|
||||
#elif defined(__AVR_ATmega1284P__)
|
||||
#define TIMER1_A_PIN 12 // PD5
|
||||
#define TIMER1_B_PIN 13 // PD4
|
||||
#define TIMER1_ICP_PIN 14 // PD6
|
||||
#define TIMER1_CLK_PIN 1 // PB1
|
||||
#define TIMER3_A_PIN 6 // PB6
|
||||
#define TIMER3_B_PIN 7 // PB7
|
||||
#define TIMER3_ICP_PIN 5 // PB5
|
||||
#define TIMER3_CLK_PIN 8 // PD0
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -2,7 +2,7 @@
|
|||
#include "farmbot_arduino_controller.h"
|
||||
#include "pins.h"
|
||||
#include "Config.h"
|
||||
|
||||
#include "StepperControl.h"
|
||||
#include "ServoControl.h"
|
||||
|
||||
static char commandEndChar = 0x0A;
|
||||
|
@ -46,6 +46,7 @@ void setup() {
|
|||
Serial.begin(115200);
|
||||
|
||||
ServoControl::getInstance()->attach();
|
||||
StepperControl::getInstance()->initInterrupt();
|
||||
|
||||
lastAction = millis();
|
||||
|
||||
|
|
Loading…
Reference in New Issue