Go Down

Topic: stepper motor turns too far (about 3 full rotations) (Read 729 times) previous topic - next topic

hrbhrb

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
Code: [Select]
const int stepsPerRevolution = 200;
Stepper myStepper(stepsPerRevolution,12,13);   

this should only turn the motor 1/200 of one rotation. Any hints?

wildbill

In a situation like this, the only way to get any meaningful help is to post the entire sketch.

hrbhrb

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:

Code: [Select]
#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);
      }
    }


}

MarkT

How are pins 5 and 6 configured and controlled?
[ I won't respond to messages, use the forum please ]

hrbhrb

Ah.. I had the pins configured like this:
Code: [Select]
    ard.sendDigitalPinMode(activePin, ARD_INPUT);
    ard.sendDigitalPinMode(directionPin, ARD_INPUT);


Changing it to
Code: [Select]
    ard.sendDigitalPinMode(activePin, ARD_OUTPUT);
    ard.sendDigitalPinMode(directionPin, ARD_OUTPUT);

did the trick. Now everything works.

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?

MarkT

Well it certainly sounded like a floating pin problem...
[ I won't respond to messages, use the forum please ]

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy