Go Down

Topic: MotorKnob like Pot output to Stepper Driver (Read 4375 times) previous topic - next topic

lbjoum

Hi,

I want to convert a Potentiometer Rotation into a discrete proportional number of pulses and a digital output for the direction that the Pot is turned, somewhat like MotorKnob.

I have a BiPolar Stepper Motor Driver that needs these inputs.

Can anyone suggest code?

cheers,
Joum


lbjoum


How about this:-
http://arduino.cc/en/Tutorial/MotorKnob


Thanks,

I have been trying this method. Even thought of leaving the Stepper Driver out of the circuit and using the H-Bridge, but the Stepper Driver is well suited to the motor and I think it will provide more reliability.

The MotorKnob code has four outputs that pulse the number of steps (and they work in pairs and reverse their polarity).  MotorKnob has no output dedicated to direction. I would have to try and build an electronic circuit to combine the pulses into one output... and I'm not sure how I would get a direction output with it.

I did look at trying to tap into the direction integer in Stepper.cpp but it got too hard.  I think there will be a solution that doesn't need the Stepper.h Library.

Code: [Select]
  // determine direction based on whether steps_to_mode is + or -:
  if (steps_to_move > 0) {this->direction = 1;}
  if (steps_to_move < 0) {this->direction = 0;}


I've only been playing with Arduino for a few days and to create the code I need might take a while, so I was hoping someone knows an existing solution.

lbjoum

Just to clarify,

I only need two outputs:
1.  The number of steps to take.
2.  The direction in which the steps will be taken.

Grumpy_Mike

It is quite simple.
Take the reading from the pot.
Use the map() function to convert this into degrees.
Compare this to the current position (the position last time)
Subtract the current position from the required position.
The sign of this gives direction, the size is proportional to the number of steps.
Convert the number of degrees into the number of steps (you know how many steps you have in 360)
Do the motion.

Most of this is simple kindergarten maths.

lbjoum

Easy if your mind is tuned to it. I am enjoying the learning curve, but I'm at the bottom.

I can see bits of what you have said in the examples of code I have found. I don't remember this math from school (20 years ago). Is it one field, like logic?

I'll have a good think about your advise and see how I go.

Thanks

lbjoum


It is quite simple.
Take the reading from the pot.
Use the map() function to convert this into degrees.
Compare this to the current position (the position last time)
Subtract the current position from the required position.
The sign of this gives direction, the size is proportional to the number of steps.
Convert the number of degrees into the number of steps (you know how many steps you have in 360)
Do the motion.

Most of this is simple kindergarten maths.



As with "the size is proportional to the number of steps", what converts a number (I guess integer) into a number of pulses?

Grumpy_Mike

Quote
As with "the size is proportional to the number of steps", what converts a number (I guess integer) into a number of pulses?


It's called division and multiplication, have you forgotten that?

if there are 200 steps in 360 degrees then there is 360 / 200 = 1.8 degrees per step. or 200 / 300 = 0.55555 steps per degree

if you want to move 20 degrees then you use 20 * 0.55555 = 11 steps

if you want to move 20 steps then you will move 20 * 1.8 = 36 degrees.

lbjoum

I don't think you understood my last question, so I will put it another way.

If i want 10 (integer) pulses (digital output), what would be an example of Code that would achieve this?

Thanks.

Grumpy_Mike

Quote
what would be an example of Code that would achieve this?


It depends on what driver you have.

If you have a step and direction driver the simply pulse the step 10 times
Code: [Select]

for(int i=0; i<10; i++){
digitalWrite(step,HIGH);
delay(1);
digitalWrite(step,LOW);
delay(200); // or what ever speed you want it to pulse at
}


are you sure you are asking the right question again?

lbjoum

Thanks,

No wonder you're Grumpy. You never sleep.

Grumpy_Mike

Ah .... I wondered why that was.  :)

Yes I was up in the night last night, sleep is not my friend sometimes.

lbjoum

I got the two outputs I was after. Number of Steps and Direction.  Some fairly blunt hacking.

Pins are 8 (number of steps) and 10 (direction)

The Post is too long so must spread it out.  Just join it back together.  I know it is the full stepper.h & stepper.cpp with an adapted MotorKnob at the end, but putting it all in one set of code was the only way i could put the direction cod into it.

Code: [Select]


/*
 Stepper.h - - Stepper library for Wiring/Arduino - Version 0.4
 
 Original library     (0.1) by Tom Igoe.
 Two-wire modifications   (0.2) by Sebastian Gassner
 Combination version   (0.3) by Tom Igoe and David Mellis
 Bug fix for four-wire   (0.4) by Tom Igoe, bug fix from Noah Shibley

 Drives a unipolar or bipolar stepper motor using  2 wires or 4 wires

 When wiring multiple stepper motors to a microcontroller,
 you quickly run out of output pins, with each motor requiring 4 connections.

 By making use of the fact that at any time two of the four motor
 coils are the inverse  of the other two, the number of
 control connections can be reduced from 4 to 2.

 A slightly modified circuit around a Darlington transistor array or an L293 H-bridge
 connects to only 2 microcontroler pins, inverts the signals received,
 and delivers the 4 (2 plus 2 inverted ones) output signals required
 for driving a stepper motor.

 The sequence of control signals for 4 control wires is as follows:

 Step C0 C1 C2 C3
    1  1  0  1  0
    2  0  1  1  0
    3  0  1  0  1
    4  1  0  0  1

 The sequence of controls signals for 2 control wires is as follows
 (columns C1 and C2 from above):

 Step C0 C1
    1  0  1
    2  1  1
    3  1  0
    4  0  0

 The circuits can be found at
 http://www.arduino.cc/en/Tutorial/Stepper
*/

// ensure this library description is only included once
#ifndef Stepper_h
#define Stepper_h

// library interface description
class Stepper {
 public:
   // constructors:
   // ** One motor_pin and one direction_pin
   Stepper(int number_of_steps, int motor_pin_1/*, int motor_pin_2*/, int direction_pin);
   //Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2, int motor_pin_3, int motor_pin_4);

   // speed setter method:
   void setSpeed(long whatSpeed);

   // mover method:
   void step(int number_of_steps);

   int version(void);

 private:
   void stepMotor(int this_step);
   
   int direction;        // Direction of rotation
   int speed;          // Speed in RPMs
   unsigned long step_delay;    // delay between steps, in ms, based on speed
   int number_of_steps;      // total number of steps this motor can take
   int pin_count;        // whether you're driving the motor with 2 or 4 pins
   int step_number;        // which step the motor is on
   
   // motor pin numbers:
   int motor_pin_1;
   int motor_pin_2;
   int motor_pin_3;
   int motor_pin_4;
   
   // Direction Pin
   int direction_pin;
   
   long last_step_time;      // time stamp in ms of when the last step was taken
};

#endif


lbjoum

Code: [Select]


/*
  Stepper.cpp - - Stepper library for Wiring/Arduino - Version 0.4
 
  Original library     (0.1) by Tom Igoe.
  Two-wire modifications   (0.2) by Sebastian Gassner
  Combination version   (0.3) by Tom Igoe and David Mellis
  Bug fix for four-wire   (0.4) by Tom Igoe, bug fix from Noah Shibley 

  Drives a unipolar or bipolar stepper motor using  2 wires or 4 wires

  When wiring multiple stepper motors to a microcontroller,
  you quickly run out of output pins, with each motor requiring 4 connections.

  By making use of the fact that at any time two of the four motor
  coils are the inverse  of the other two, the number of
  control connections can be reduced from 4 to 2.

  A slightly modified circuit around a Darlington transistor array or an L293 H-bridge
  connects to only 2 microcontroler pins, inverts the signals received,
  and delivers the 4 (2 plus 2 inverted ones) output signals required
  for driving a stepper motor.

  The sequence of control signals for 4 control wires is as follows:

  Step C0 C1 C2 C3
     1  1  0  1  0
     2  0  1  1  0
     3  0  1  0  1
     4  1  0  0  1

  The sequence of controls signals for 2 control wires is as follows
  (columns C1 and C2 from above):

  Step C0 C1
     1  0  1
     2  1  1
     3  1  0
     4  0  0

  The circuits can be found at

http://www.arduino.cc/en/Tutorial/Stepper


*/
// set pin numbers:
const int dirPin =  10;      // the number of the LED pin



// Variables will change:
int dirState = LOW;             // ledState used to set the LED
long previousMillis = 0;        // will store last time LED was updated

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 0;           // interval at which to blink (milliseconds)


#include "WProgram.h"
//#include "Stepper.h"

/*
* two-wire constructor.
* Sets which wires should control the motor.
*/
// ** One motor_Pin and direction_pin

Stepper::Stepper(int number_of_steps, int motor_pin_1/*, int motor_pin_2*/, int direction_pin)
{
  this->step_number = 0;      // which step the motor is on
  this->speed = 0;        // the motor speed, in revolutions per minute
  this->direction = 0;      // motor direction
  this->last_step_time = 0;    // time stamp in ms of the last step taken
  this->number_of_steps = number_of_steps;    // total number of steps for this motor
 
  // Arduino pins for the motor control connection:
  this->motor_pin_1 = motor_pin_1;
  this->motor_pin_2 = motor_pin_2;

  // setup the pins on the microcontroller:
  pinMode(this->motor_pin_1, OUTPUT);
  //pinMode(this->motor_pin_2, OUTPUT);
  // Direction Pin
  pinMode(this->direction_pin, OUTPUT);
  this->direction_pin = dirPin;
 
  // When there are only 2 pins, set the other two to 0:
  // Only 1 motor_pin
  this->motor_pin_2 = 0;
  this->motor_pin_3 = 0;
  this->motor_pin_4 = 0;

  // pin_count is used by the stepMotor() method:
  //this->pin_count = 2;
  this->pin_count = 1;
}


/*
*   constructor for four-pin version
*   Sets which wires should control the motor.
*/
/*
Stepper::Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2, int motor_pin_3, int motor_pin_4)
{
  this->step_number = 0;      // which step the motor is on
  this->speed = 0;        // the motor speed, in revolutions per minute
  this->direction = 0;      // motor direction
  this->last_step_time = 0;    // time stamp in ms of the last step taken
  this->number_of_steps = number_of_steps;    // total number of steps for this motor
 
  // Arduino pins for the motor control connection:
  this->motor_pin_1 = motor_pin_1;
  this->motor_pin_2 = motor_pin_2;
  this->motor_pin_3 = motor_pin_3;
  this->motor_pin_4 = motor_pin_4;

  // setup the pins on the microcontroller:
  pinMode(this->motor_pin_1, OUTPUT);
  pinMode(this->motor_pin_2, OUTPUT);
  pinMode(this->motor_pin_3, OUTPUT);
  pinMode(this->motor_pin_4, OUTPUT);

  // pin_count is used by the stepMotor() method: 
  this->pin_count = 4; 
}
*/

/*
  Sets the speed in revs per minute

*/
void Stepper::setSpeed(long whatSpeed)
{
  this->step_delay = 60L * 1000L / this->number_of_steps / whatSpeed;
}

/*
  Moves the motor steps_to_move steps.  If the number is negative,
   the motor moves in the reverse direction.
*/
void Stepper::step(int steps_to_move)

  int steps_left = abs(steps_to_move);  // how many steps to take
 
  // determine direction based on whether steps_to_mode is + or -:
  if (steps_to_move > 0) {this->direction = 1;}
  if (steps_to_move < 0) {this->direction = 0;}
   

  // Attempt to write Direction

  // set the dir digital pin as output:
  pinMode(dirPin, OUTPUT);     

unsigned long currentMillis = millis();

  if(currentMillis - previousMillis > interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;   

    // if the dirPin is off turn it on and vice-versa:
    if (this->direction == 1)
      dirState = HIGH;
    else
      dirState = LOW;

    // set the LED with the ledState of the variable:
    digitalWrite(dirPin, dirState);
  }

/*
// Attempt to write Direction
  if (this->direction == 1) {
        digitalWrite(direction_pin, HIGH);
         delay(1000);              // wait for a second
  }
 
        else
        {
        digitalWrite(direction_pin, LOW);
         delay(1000);              // wait for a second
}
*/
  // decrement the number of steps, moving one step each time:
  while(steps_left > 0) {
  // move only if the appropriate delay has passed:
  if (millis() - this->last_step_time >= this->step_delay) {
      // get the timeStamp of when you stepped:
      this->last_step_time = millis();
      // increment or decrement the step number,
      // depending on direction:
      if (this->direction == 1) {
        this->step_number++;
        if (this->step_number == this->number_of_steps) {
          this->step_number = 0;
        }
      }
      else {
        if (this->step_number == 0) {
          this->step_number = this->number_of_steps;
        }
        this->step_number--;
      }
      // decrement the steps left:
      steps_left--;
      // step the motor to step number 0, 1, 2, or 3:
      stepMotor(this->step_number % 4);
    }
  }
}


/*
* Moves the motor forward or backwards.
*/
void Stepper::stepMotor(int thisStep)

{
  if (this->pin_count == 1) {
    // I think "switch" sets up a walk through each case.
    switch (thisStep) {
      case 0: /* 01 */
      digitalWrite(motor_pin_1, LOW);
     
      break;
      case 1: /* 11 */
      digitalWrite(motor_pin_1, HIGH);
     
      break;
     
    }
  }

  if (this->pin_count == 2) {
    switch (thisStep) {
      case 0: /* 01 */
      digitalWrite(motor_pin_1, LOW);
      digitalWrite(motor_pin_2, HIGH);
      break;
      case 1: /* 11 */
      digitalWrite(motor_pin_1, HIGH);
      digitalWrite(motor_pin_2, HIGH);
      break;
      case 2: /* 10 */
      digitalWrite(motor_pin_1, HIGH);
      digitalWrite(motor_pin_2, LOW);
      break;
      case 3: /* 00 */
      digitalWrite(motor_pin_1, LOW);
      digitalWrite(motor_pin_2, LOW);
      break;
    }
  }
  if (this->pin_count == 4) {
    switch (thisStep) {
      case 0:    // 1010
      digitalWrite(motor_pin_1, HIGH);
      digitalWrite(motor_pin_2, LOW);
      digitalWrite(motor_pin_3, HIGH);
      digitalWrite(motor_pin_4, LOW);
      break;
      case 1:    // 0110
      digitalWrite(motor_pin_1, LOW);
      digitalWrite(motor_pin_2, HIGH);
      digitalWrite(motor_pin_3, HIGH);
      digitalWrite(motor_pin_4, LOW);
      break;
      case 2:    //0101
      digitalWrite(motor_pin_1, LOW);
      digitalWrite(motor_pin_2, HIGH);
      digitalWrite(motor_pin_3, LOW);
      digitalWrite(motor_pin_4, HIGH);
      break;
      case 3:    //1001
      digitalWrite(motor_pin_1, HIGH);
      digitalWrite(motor_pin_2, LOW);
      digitalWrite(motor_pin_3, LOW);
      digitalWrite(motor_pin_4, HIGH);
      break;
    }
  }


}
 

/*
  version() returns the version of the library:
*/
int Stepper::version(void)
{
  return 4;
}


/*
* MotorKnob
*
* A stepper motor follows the turns of a potentiometer
* (or other sensor) on analog input 0.
*
* http://www.arduino.cc/en/Reference/Stepper
* This example code is in the public domain.
*/

//#include <Stepper.h>

// change this to the number of steps on your motor
#define STEPS 100

// create an instance of the stepper class, specifying
// the number of steps of the motor and the pins it's
// attached to
// Pin 8 Steps and 10 Direction
Stepper stepper(STEPS, 8, 10);

// the previous reading from the analog input
int previous = 0;

void setup()
{
  // set the speed of the motor to 30 RPMs
  stepper.setSpeed(30);
}

void loop()
{
  // get the sensor value
  //int val = analogRead(0);
  //Read analog 0 (pot) and map it to the range of the motor
  int val = map(analogRead(0), 0, 1023, 400, 0);
 
  // move a number of steps equal to the change in the
  // sensor reading
  stepper.step(val - previous);

  // remember the previous value of the sensor
  previous = val;
};

lbjoum

Update:
I cleaned up the code.  Even though the input is re-mapped the pot is to sensitive.  When the Pot is Stationary the outputs both jitter. Any ideas how to stabilize?
Code: [Select]
// JoumStepDir2

/* 
  Original library     (0.1) by Tom Igoe.
  Two-wire modifications   (0.2) by Sebastian Gassner
  Combination version   (0.3) by Tom Igoe and David Mellis
*/

// library interface description
class Stepper {
  public:
    // constructors:
    // ** One motor_pin and one direction_pin
    Stepper(int number_of_steps, int motor_pin_1, int direction_pin);

    // speed setter method:
    void setSpeed(long whatSpeed);

    // mover method:
    void step(int number_of_steps);

    int version(void);

    void stepMotor(int this_step);
   
    int direction;        // Direction of rotation
    int speed;          // Speed in RPMs
    unsigned long step_delay;    // delay between steps, in ms, based on speed
    int number_of_steps;      // total number of steps this motor can take
    int pin_count;        // whether you're driving the motor with 2 or 4 pins
    int step_number;        // which step the motor is on
   
    // motor pin number:
    int motor_pin_1;

    // direction pin number
    int direction_pin;
   
    long last_step_time;      // time stamp in ms of when the last step was taken
};
//-------------------------end stepper.h

// Variables will change:
int dirState = LOW;             // dirState used to set the direction_pin
long previousMillis = 0;        // will store last time direction_pin was updated

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 0;           // interval at which to blink (milliseconds)

#include "WProgram.h"

/*
* two-wire constructor.
* Sets which wires should control the motor.
*/
// ** One motor_Pin and direction_pin

Stepper::Stepper(int number_of_steps, int motor_pin_1, int direction_pin)
{
  this->step_number = 0;      // which step the motor is on
  this->speed = 0;        // the motor speed, in revolutions per minute
  this->direction = 0;      // motor direction
  this->last_step_time = 0;    // time stamp in ms of the last step taken
  this->number_of_steps = number_of_steps;    // total number of steps for this motor
 
  // Arduino pins for the motor control connection:
  this->motor_pin_1 = motor_pin_1;

  // setup the pins on the microcontroller:
  pinMode(this->motor_pin_1, OUTPUT);

  // Direction Pin
this->direction_pin = direction_pin;
 
  // pin_count is used by the stepMotor() method:
this->pin_count = 1;

}



   // mover method:
    void step(int number_of_steps);

    int version(void);

/*
  Sets the speed in revs per minute

*/
void Stepper::setSpeed(long whatSpeed)
{
  this->step_delay = 60L * 1000L / this->number_of_steps / whatSpeed;
}

/*
  Moves the motor steps_to_move steps.  If the number is negative,
   the motor moves in the reverse direction.
*/
void Stepper::step(int steps_to_move)


  int steps_left = abs(steps_to_move);  // how many steps to take
 
  // determine direction based on whether steps_to_mode is + or -:
  if (steps_to_move > 0) {this->direction = 1;}
  if (steps_to_move < 0) {this->direction = 0;}
   

  // Attempt to write Direction

  // set the dir digital pin as output:
  pinMode(direction_pin, OUTPUT);     

unsigned long currentMillis = millis();

  if(currentMillis - previousMillis > interval) {
    // save the last time you blinked the direction_pin
    previousMillis = currentMillis;   

    // if the direction_pin is off turn it on and vice-versa:
    if (this->direction == 1)
      dirState = HIGH;
    else
      dirState = LOW;

    // set the direction_pin with the dirState of the variable:
    digitalWrite(direction_pin, dirState);
  }

  // decrement the number of steps, moving one step each time:
  while(steps_left > 0) {
  // move only if the appropriate delay has passed:
  if (millis() - this->last_step_time >= this->step_delay) {
      // get the timeStamp of when you stepped:
      this->last_step_time = millis();
      // increment or decrement the step number,
      // depending on direction:
      if (this->direction == 1) {
        this->step_number++;
        if (this->step_number == this->number_of_steps) {
          this->step_number = 0;
        }
      }
      else {
        if (this->step_number == 0) {
          this->step_number = this->number_of_steps;
        }
        this->step_number--;
      }
      // decrement the steps left:
      steps_left--;
      // step the motor to step number 0, 1, 2, or 3:
      stepMotor(this->step_number % 4);
    }
  }
}


/*
* Moves the motor forward or backwards.
*/
void Stepper::stepMotor(int thisStep)

{
  if (this->pin_count == 1) {
    // I think "switch" sets up a walk through each case.
    switch (thisStep) {
      case 0: /* 01 */
      digitalWrite(motor_pin_1, LOW);
     
      break;
      case 1: /* 11 */
      digitalWrite(motor_pin_1, HIGH);
     
      break;
     
    }
  }
}

/*
  version() returns the version of the library:
*/
int Stepper::version(void)
{
  return 4;
}

/*
* MotorKnob
*
* A stepper motor follows the turns of a potentiometer
* (or other sensor) on analog input 0.
*
* http://www.arduino.cc/en/Reference/Stepper
* This example code is in the public domain.
*/


// change this to the number of steps on your motor
#define STEPS 100

// create an instance of the stepper class, specifying
// the number of steps of the motor and the pins it's
// attached to
// Pin 8 Steps and 10 Direction
Stepper stepper(STEPS, 6, 7);

// the previous reading from the analog input
int previous = 0;

void setup()
{
  // set the speed of the motor to 30 RPMs
  stepper.setSpeed(30);
}

void loop()
{
  // get the sensor value
  //int val = analogRead(0);
  //Read analog 0 (pot) and map it to the range of the motor
  int val = map(analogRead(0), 0, 1023, 48, 0);
 
  // move a number of steps equal to the change in the
  // sensor reading
  stepper.step(val - previous);

  // remember the previous value of the sensor
  previous = val;
}

Go Up