Hi,
I'm trying to control a stepper motor with Arduino Uno and the MotorShield. But when I move it fast - doesn't matter if I use Stepper.h or do it 'manually' with short delay times - it moves for about 3 full rotations.
So even if I do something like myStepper.step(1) I get 3 rotations. With
const int stepsPerRevolution = 200;
Stepper myStepper(stepsPerRevolution,12,13);
this should only turn the motor 1/200 of one rotation. Any hints?
Yes I know. It took me a while to clean it up a bit.
Basically it's a simple firmata version with a stepper motor control. I use it with an openframeworks application. The application sets 2 pins. One to activate the motor, one for the direction.
My last version started delayed and ended delayed. This one starts instantly - when I activate the motor from the of application it starts turning instantly. But I still have the problem that the motor keeps turning for a while after i deactivate it from my application.
Anyway, here's my arduino sketch:
#include <Stepper.h>
#include <Firmata.h>
/*==============================================================================
* GLOBAL VARIABLES
*============================================================================*/
const int stepsPerRevolution = 200; // change this to fit the number of steps per revolution
// for your motor
// initialize the stepper library on the motor shield
Stepper myStepper(stepsPerRevolution,12,13);
// give the motor control pins names:
const int pwmA = 3;
const int pwmB = 11;
const int brakeA = 9;
const int brakeB = 8;
const int activateMotorPin = 5;
const int directionPin = 6;
/* analog inputs */
int analogInputsToReport = 0; // bitwise array to store pin reporting
int analogPin = 0; // counter for reading analog pins
/* timer variables */
unsigned long currentMillis; // store the current value from millis()
unsigned long previousMillis; // for comparison with currentMillis
byte previousPIN[TOTAL_PORTS]; // PIN means PORT for input
byte previousPORT[TOTAL_PORTS];
/*==============================================================================
* FUNCTIONS
*============================================================================*/
void outputPort(byte portNumber, byte portValue)
{
// only send the data when it changes, otherwise you get too many messages!
if (previousPIN[portNumber] != portValue) {
Firmata.sendDigitalPort(portNumber, portValue);
previousPIN[portNumber] = portValue;
}
}
void setPinModeCallback(byte pin, int mode) {
if (IS_PIN_DIGITAL(pin)) {
pinMode(PIN_TO_DIGITAL(pin), mode);
}
}
void digitalWriteCallback(byte port, int value)
{
byte i;
byte currentPinValue, previousPinValue;
if (port < TOTAL_PORTS && value != previousPORT[port]) {
for(i=0; i<8; i++) {
currentPinValue = (byte) value & (1 << i);
previousPinValue = previousPORT[port] & (1 << i);
if(currentPinValue != previousPinValue) {
digitalWrite(i + (port*8), currentPinValue);
}
}
previousPORT[port] = value;
}
}
void analogWriteCallback(byte pin, int value)
{
switch(pin) {
case 3:
case 5:
case 6:
case 11: // PWM pins
analogWrite(pin, value);
break;
}
}
// -----------------------------------------------------------------------------
// sets bits in a bit array (int) to toggle the reporting of the analogIns
void reportAnalogCallback(byte pin, int value)
{
if(value == 0) {
analogInputsToReport = analogInputsToReport &~ (1 << pin);
}
else { // everything but 0 enables reporting of that pin
analogInputsToReport = analogInputsToReport | (1 << pin);
}
// TODO: save status to EEPROM here, if changed
}
/*==============================================================================
* SETUP()
*============================================================================*/
void setup()
{
// set the PWM and brake pins so that the direction pins // can be used to control the motor:
pinMode(pwmA, OUTPUT);
pinMode(pwmB, OUTPUT);
pinMode(brakeA, OUTPUT);
pinMode(brakeB, OUTPUT);
digitalWrite(pwmA, HIGH);
digitalWrite(pwmB, HIGH);
digitalWrite(brakeA, LOW);
digitalWrite(brakeB, LOW);
// set the motor speed (for multiple steps only):
myStepper.setSpeed(120);
Firmata.setFirmwareVersion(0, 2);
Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
Firmata.attach(REPORT_ANALOG, reportAnalogCallback);
Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
Firmata.attach(SET_PIN_MODE, setPinModeCallback);
Firmata.begin(57600);
}
/*==============================================================================
* LOOP()
*============================================================================*/
void loop()
{
byte i;
for (i=0; i<TOTAL_PORTS; i++) {
outputPort(i, readPort(i, 0xff));
}
while(Firmata.available())
Firmata.processInput();
currentMillis = millis();
if(currentMillis - previousMillis > 20) {
previousMillis += 20; // run this every 20ms
for(analogPin=0;analogPin<TOTAL_ANALOG_PINS;analogPin++) {
if( analogInputsToReport & (1 << analogPin) )
Firmata.sendAnalog(analogPin, analogRead(analogPin));
}
}
if(digitalRead(activateMotorPin) == HIGH) {
if(digitalRead(directionPin) == HIGH) {
myStepper.step(5);
}
else if(digitalRead(directionPin) == LOW) {
myStepper.step(-5);
}
}
}
I still have one question though: now I'm able to turn the motor on/off. If I also want to change its speed from my openframeworks app how would I do it? Use an analog pin to send a speed value to the arduino board? Or are there any other options?