Files
arduino/libraries/FirmataWithDeviceFeature/src-features/StepperFirmata.cpp
2018-08-08 08:33:26 +02:00

152 lines
5.1 KiB
C++

/*
Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved.
Copyright (C) 2010-2011 Paul Stoffregen. All rights reserved.
Copyright (C) 2009 Shigeru Kobayashi. All rights reserved.
Copyright (C) 2013 Norbert Truchsess. All rights reserved.
Copyright (C) 2009-2016 Jeff Hoefs. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
See file LICENSE.txt for further informations on licensing terms.
Last updated by Jeff Hoefs: January 23rd, 2016
*/
#include <ConfigurableFirmata.h>
#include "StepperFirmata.h"
#include "utility/FirmataStepper.h"
boolean StepperFirmata::handlePinMode(byte pin, int mode)
{
if (mode == PIN_MODE_STEPPER) {
if (IS_PIN_DIGITAL(pin)) {
digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable PWM
pinMode(PIN_TO_DIGITAL(pin), OUTPUT);
return true;
}
}
return false;
}
void StepperFirmata::handleCapability(byte pin)
{
if (IS_PIN_DIGITAL(pin)) {
Firmata.write(PIN_MODE_STEPPER);
Firmata.write(21); //21 bits used for number of steps
}
}
/*==============================================================================
* SYSEX-BASED commands
*============================================================================*/
boolean StepperFirmata::handleSysex(byte command, byte argc, byte *argv)
{
if (command == STEPPER_DATA) {
byte stepCommand, deviceNum, directionPin, stepPin, stepDirection;
byte interface, interfaceType;
byte motorPin3, motorPin4;
unsigned int stepsPerRev;
long numSteps;
int stepSpeed;
int accel;
int decel;
stepCommand = argv[0];
deviceNum = argv[1];
if (deviceNum < MAX_STEPPERS) {
if (stepCommand == STEPPER_CONFIG) {
interface = argv[2]; // upper 4 bits are the stepDelay, lower 4 bits are the interface type
interfaceType = interface & 0x0F; // the interface type is specified by the lower 4 bits
stepsPerRev = (argv[3] + (argv[4] << 7));
directionPin = argv[5]; // or motorPin1 for TWO_WIRE or FOUR_WIRE interface
stepPin = argv[6]; // // or motorPin2 for TWO_WIRE or FOUR_WIRE interface
if (Firmata.getPinMode(directionPin) == PIN_MODE_IGNORE || Firmata.getPinMode(stepPin) == PIN_MODE_IGNORE)
return false;
Firmata.setPinMode(directionPin, PIN_MODE_STEPPER);
Firmata.setPinMode(stepPin, PIN_MODE_STEPPER);
if (!stepper[deviceNum]) {
numSteppers++;
}
if (interfaceType == FirmataStepper::DRIVER || interfaceType == FirmataStepper::TWO_WIRE) {
stepper[deviceNum] = new FirmataStepper(interface, stepsPerRev, directionPin, stepPin);
} else if (interfaceType == FirmataStepper::FOUR_WIRE) {
motorPin3 = argv[7];
motorPin4 = argv[8];
if (Firmata.getPinMode(motorPin3) == PIN_MODE_IGNORE || Firmata.getPinMode(motorPin4) == PIN_MODE_IGNORE)
return false;
Firmata.setPinMode(motorPin3, PIN_MODE_STEPPER);
Firmata.setPinMode(motorPin4, PIN_MODE_STEPPER);
stepper[deviceNum] = new FirmataStepper(interface, stepsPerRev, directionPin, stepPin, motorPin3, motorPin4);
}
}
else if (stepCommand == STEPPER_STEP) {
stepDirection = argv[2];
numSteps = (long)argv[3] | ((long)argv[4] << 7) | ((long)argv[5] << 14);
stepSpeed = (argv[6] + (argv[7] << 7));
if (stepDirection == 0) {
numSteps *= -1;
}
if (stepper[deviceNum]) {
if (argc >= 8 && argc < 12) {
// num steps, speed (0.01*rad/sec)
stepper[deviceNum]->setStepsToMove(numSteps, stepSpeed);
} else if (argc == 12) {
accel = (argv[8] + (argv[9] << 7));
decel = (argv[10] + (argv[11] << 7));
// num steps, speed (0.01*rad/sec), accel (0.01*rad/sec^2), decel (0.01*rad/sec^2)
stepper[deviceNum]->setStepsToMove(numSteps, stepSpeed, accel, decel);
}
}
}
return true;
}
}
return false;
}
/*==============================================================================
* SETUP()
*============================================================================*/
void StepperFirmata::reset()
{
for (byte i = 0; i < MAX_STEPPERS; i++) {
if (stepper[i]) {
free(stepper[i]);
stepper[i] = 0;
}
}
numSteppers = 0;
}
/*==============================================================================
* LOOP()
*============================================================================*/
void StepperFirmata::update()
{
if (numSteppers > 0) {
// if one or more stepper motors are used, update their position
for (byte i = 0; i < MAX_STEPPERS; i++) {
if (stepper[i]) {
bool done = stepper[i]->update();
// send command to client application when stepping is complete
if (done) {
Firmata.write(START_SYSEX);
Firmata.write(STEPPER_DATA);
Firmata.write(i);
Firmata.write(END_SYSEX);
}
}
}
}
}