Go Down

Topic: Coding a Revolution Counter for a Stepper Motor. (Read 590 times) previous topic - next topic

PatrickZ

Nov 14, 2019, 07:23 am Last Edit: Nov 14, 2019, 07:40 am by PatrickZ
Hello,

Coding a Revolution Counter for a Stepper Motor, Id like to pre-program in the source code a fixed number of revolutions. Each 200 steps decrements 1 from the "pre-programmed" number until zero, motor stop.

there are 1000 possible counts, so there are 3 seven segment units with the 4th thousands place is just a 2 segment led for the "1"

So is it possible to count from 1000 to 0 revolutions while outputing a BCD output in real time for 3 LED displays? Ill use direction and pulse pins for the motor to an external H-Bridge, and three 7447 decoders to drive the 3 digits. Ill also use the potentiometer in real time to make fine adjustments to speed.

Also i dont know if (turns decrement 1) can be put at the end of void loop and execute once after every 200 steps?

Ive seen code but dont know how to do conversion to BCD and assign it to output pins.

Some code ive been modding:
Code: [Select]


/*
 Stepper Motor Control - speed control

 This program drives a unipolar or bipolar stepper motor.
 The motor is attached to digital pins 8 - 11 of the Arduino.
 A potentiometer is connected to analog input 0.

 The motor will rotate in a clockwise direction. The higher the potentiometer value,
 the faster the motor speed. Because setSpeed() sets the delay between steps,
 you may notice the motor is less responsive to changes in the sensor value at
 low speeds.

 Created 30 Nov. 2009
 Modified 28 Oct 2010
 by Tom Igoe

 */

#include <Stepper.h>

const int stepsPerRevolution = 200;  // change this to fit the number of steps per revolution
// for your motor


// initialize the stepper library on pins 8 through 11:
Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);

int stepCount = 0;  // number of steps the motor has taken

void setup() {
  // nothing to do inside the setup
}

void loop() {
  // read the sensor value:
  int sensorReading = analogRead(A0);
  // map it to a range from 0 to 100:
  int motorSpeed = map(sensorReading, 0, 1023, 0, 100);
  // set the motor speed:
  if (motorSpeed > 0) {
    myStepper.setSpeed(motorSpeed);
    // step 1/100 of a revolution:
    myStepper.step(stepsPerRevolution / 100);
  }
}



Pic to follow:

Robin2

You have told us that you want to change the rev count every 200 steps, but you have not told us what commands you are giving to the motor.

If you command the motor to move 200 steps at a time then you can just increment the counter each time the motor is told to move.

If you want the motor to move (say) 1000 steps and you want to update the counter every 200 steps then the standard stepper library is not really suitable because it will block the Arduino until all 1000 steps are complete.

There are two options. The AccelStepper library has a function distanceToGo() which reports how many steps are left. Or you could use the standard stepper library and move the motor one step at a time using your own code to do the step timing.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

PatrickZ

#2
Nov 14, 2019, 07:45 pm Last Edit: Nov 14, 2019, 07:59 pm by PatrickZ
Yes I was worried I wasnt explaining it well.

Quote
You have told us that you want to change the rev count every 200 steps, but you have not told us what commands you are giving to the motor.
It would be a potentiometer to speed up or slow down the simple code Ive seen is good enough, the speed update and resolution doesnt need to be super accurate. (The 200 steps per rev needs to be perfect obviously.)


Quote
If you command the motor to move 200 steps at a time then you can just increment the counter each time the motor is told to move.
Yes every 200 steps decrement the counter value by 1. This should be simple odometry like a robot car.

Quote
If you want the motor to move (say) 1000 steps and you want to update the counter every 200 steps then the standard stepper library is not really suitable because it will block the Arduino until all 1000 steps are complete.
Not sure i understand...
Updating the counter slowly is fine, the rotational speed would be one rotation per 3 seconds, so slow compared to most stepper uses.

Quote
standard stepper library is not really suitable because it will block the Arduino until all 1000 steps are complete.
not sure what to do, this doesnt sound good. Could i program it to slowly ramp up/down  to its new speed when each 200th step was completed ?

 
This device is for winding coils, transformers and motors.






MorganS

Yes every 200 steps decrement the counter value by 1. This should be simple odometry like a robot car.
You mean every step, decrement the counter by 1. Display counter/stepsPerRevolution on the display. (Notice I don't use the magic-number "200".) So long as you use a variable big enough, you can take millions of steps and the division operation is still "accurate".

The AccelStepper library may be preferable, since it can easily do linear accelerations and decellerations. Tell it to move a million steps and it will smoothly speed up, run and slow down to a stop at the end.

"The problem is in the code you didn't post."

Robin2

Not sure i understand...
Updating the counter slowly is fine, the rotational speed would be one rotation per 3 seconds, so slow compared to most stepper uses.
I'm inclined to think I don't understand your requirement.

I thought the problem was that you could not (or did not know how to) increment (or decrement) a counter after every revolution of the motor if the Stepper library has been asked to do a large number of steps.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

PatrickZ

#5
Nov 17, 2019, 06:04 am Last Edit: Nov 17, 2019, 08:11 am by PatrickZ
2 functions are needed.

- Counting down 1000 to 0.
- Variable rotation speed.

So 1000 then 200 steps, 999 then 200 steps. and so on till zero. While a pot controls the speed faster or slower but always clockwise.


Code: [Select]
/*
 Stepper Motor Control - speed control

 This program drives a unipolar or bipolar stepper motor.
 The motor is attached to digital pins 8 - 11 of the Arduino.
 A potentiometer is connected to analog input 0.

 The motor will rotate in a clockwise direction. The higher the potentiometer value,
 the faster the motor speed. Because setSpeed() sets the delay between steps,
 you may notice the motor is less responsive to changes in the sensor value at
 low speeds.

 Created 30 Nov. 2009
 Modified 28 Oct 2010
 by Tom Igoe

 */

#include <Stepper.h>

const int stepsPerRevolution = 200;  // change this to fit the number of steps per revolution
// for your motor


// initialize the stepper library on pins 8 through 11:
Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);

int stepCount = 0;  // number of steps the motor has taken
int RotationsNeeded = 1000; // count down display value
int Display = 0;

void setup() {
  
    Serial.begin(9600); // open the serial port at 9600 bps:
}

void loop() {
  // read the sensor value:
  int sensorReading = analogRead(A0);
  // map it to a range from 0 to 100:
  int motorSpeed = map(sensorReading, 0, 1023, 0, 100);
  // set the motor speed:
  if (motorSpeed > 0) {
    myStepper.setSpeed(motorSpeed);
    // step 1/100 of a revolution:
    myStepper.step(stepsPerRevolution / 100);
  }

 Display = RotationsNeeded--;

// new area for serial monitor code

  // print labels
  Serial.print("Count down");  // prints a label
  Serial.print("\t");         // prints a tab
  Serial.println();        // carriage return after the last label
  
    Serial.print(Display);       // print as an ASCII-encoded decimal - same as "DEC"
    Serial.print("\t\t");  // prints two tabs to accomodate the label lenght

    Serial.println();  // print as an ASCII-encoded binary
    // then adds the carriage return with "println"
    delay(200);            // delay 200 milliseconds

}

this is sort of what i crammed together, turn up or down the speed as needed with a pot, while decrementing 1 for every 200 steps of a 200 step motor. I may use a peg or bump to press a micro-switch to do the decrement, it would guarantee the right rotation count even with lost steps. but i would rather a software solution...

It still needs to convert the "Display" variable to BCD and the assign them to pins.


Robin2

#6
Nov 17, 2019, 10:34 am Last Edit: Nov 17, 2019, 10:35 am by Robin2
2 functions are needed.

- Counting down 1000 to 0.
- Variable rotation speed.
You have not addressed my understanding of the problem as set out in Reply #4. It is much easier to help when your replies follow on from comments you have received so there is a stream of development of ideas rather than things popping up out of the blue. And if you don't understand something please say so - it can save a lot of wasted time.

Also you have posted a program but you have not told us what happens when your run it.

As far as I can see your program causes the motor to move 2 steps at the set speed and then print stuff and wait 200 millisecs before the next 2 steps.

Is that correct, and is it what you want it to do?

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Paul_KD7HB

You wrote: "This device is for winding coils, transformers and motors. ".

I have some experience building a coil winder. You need to factor in an emergency pause/continue switch in your coding and physical design.

Paul

PatrickZ

#8
Nov 18, 2019, 01:24 am Last Edit: Nov 18, 2019, 01:25 am by PatrickZ
As far as I can see your program causes the motor to move 2 steps at the set speed and then print stuff and wait 200 millisecs before the next 2 steps.

Is that correct, and is it what you want it to do?

...R
I dont know how else to describe my need... revolve once decrement by 1, revolve again decrement again until zero, then stop... all while i can speed up or slow down in real time to avoid tangles or breaking the wire. My digital logic analyzer Isnt working and serial monitor only shows the decrement count. Eventually the code would put out BCD for the LED segments as seen in the beginning pic.

And no what you describe is not what i want.

the emergency stop is easy compared to the rest of this.

Robin2

#9
Nov 18, 2019, 09:54 am Last Edit: Nov 18, 2019, 10:03 am by Robin2
I dont know how else to describe my need... revolve once decrement by 1, revolve again decrement again until zero, then stop... all while i can speed up or slow down in real time to avoid tangles or breaking the wire.
That description reads as if you would be content for the motor to move 1 rev, stop, decrement the counter, do the next rev, stop, decrement the counter etc. Keep in mind that computers are stupid and interpret instructions literally - they have no capability to figure out what you want.

My guess is that what you really want is for the motor to run continuously for (perhaps) several hundred revs decrementing the counter as each rev is completed.

If so, you need to re-read the last paragraph in Reply #1 for two options for implementing that.

I suggest you try some of the examples that come with the AccelStepper library and study its documentation so you understand how it can be used.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

PatrickZ

#10
Nov 19, 2019, 02:54 pm Last Edit: Nov 19, 2019, 03:08 pm by PatrickZ
My guess is that what you really want is for the motor to run continuously for (perhaps) several hundred revs decrementing the counter as each rev is completed.

Yes that is what i want.

Code: [Select]
// ProportionalControl.pde
// -*- mode: C++ -*-
//
// Make a single stepper follow the analog value read from a pot or whatever
// The stepper will move at a constant speed to each newly set posiiton,
// depending on the value of the pot.
//
// Copyright (C) 2012 Mike McCauley
// $Id: ProportionalControl.pde,v 1.1 2011/01/05 01:51:01 mikem Exp mikem $
#include <AccelStepper.h>
// Define a stepper and the pins it will use
AccelStepper stepper; // Defaults to AccelStepper::FULL4WIRE (4 pins) on 2, 3, 4, 5
// This defines the analog input pin for reading the control voltage
// Tested with a 10k linear pot between 5v and GND
#define ANALOG_IN A0
void setup()
{  
  stepper.setMaxSpeed(1000);
}
void loop()
{
  // Read new position
  int analog_in = analogRead(ANALOG_IN);
  stepper.moveTo(analog_in);
  stepper.setSpeed(100);
  stepper.runSpeedToPosition();
}

 This code does the analog in speed control like i want. But i dont see the step/rev that all code needs to know what each steppers step per degree is. my motor is 200 steps per turn. Im trying to use the link you provided.

Robin2

You have chosen an inappropriate example from the AccelStepper library because runSpeedToPosition() blocks until it completes.

You need to use run() [which uses acceleration] or runSpeed() [which does not]. Study the examples for those functions.

Suppose that you tell the motor to go 1000 steps with myStepper.move(1000);  Then in every iteration of loop() you can check how far it has got with code in loop() like this

Code: [Select]
previousPosition = currentPosition;
currentPosition = myStepper.distanceToGo();
if (currentPosition > previousPosition) {
  stepsThisRev ++;
}
if (stepsThisRev >= 200) {
   numRevs --;
   stepsThisRev = 0;
}


Make sure that loop() can repeat much faster than the step rate.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

PatrickZ

#12
Nov 20, 2019, 10:49 pm Last Edit: Nov 20, 2019, 10:49 pm by PatrickZ
Code: [Select]
previousPosition = currentPosition;
currentPosition = myStepper.distanceToGo();
if (currentPosition > previousPosition) {
  stepsThisRev ++;
}
if (stepsThisRev >= 200) {
   numRevs --;
   stepsThisRev = 0;
}

 Does this go in the void loop section, and more in the void setup ? ive been looking here :

https://www.airspayce.com/mikem/arduino/AccelStepper/classAccelStepper.html#aa4a6bdf99f698284faaeb5542b0b7514

Robin2

Does this go in the void loop section, and more in the void setup ?
It must go in the loop() function (or be called from loop() ) as it needs to be checked regularly.

You will need to declare the relevant variable before the setup() function.


I suspect you would benefit from taking a little time to study the basics of Arduino C++ programming so you have a better idea where things need to go in programs.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

johnwasser

There is not enough information to tell you how to display a number on your 7-segment displays.  A wiring diagram would help.
Code: [Select]
/*
  Stepper Motor Control - speed control


  This program drives a unipolar or bipolar stepper motor.
  The motor is attached to digital pins 8 - 11 of the Arduino.
  A potentiometer is connected to analog input 0.


  The motor will rotate in a clockwise direction. The higher the potentiometer value,
  the faster the motor speed. Because setSpeed() sets the delay between steps,
  you may notice the motor is less responsive to changes in the sensor value at
  low speeds.


  Created 30 Nov. 2009
  Modified 28 Oct 2010
  by Tom Igoe


*/


#include <Stepper.h>


const int stepsPerRevolution = 200;  // change this to fit the number of steps per revolution
// for your motor

// initialize the stepper library on pins 8 through 11:
Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);


long int stepCount = 0;  // number of steps the motor has taken


void setup()
{
  // nothing to do inside the setup
}


void display(int value)
{
  // Display the value on the 3+ digit display
}


void loop()
{
  // read the sensor value:
  int sensorReading = analogRead(A0);
  
  // map it to a range from 0 to 100:
  int motorSpeed = map(sensorReading, 0, 1023, 0, 100);
  
  // set the motor speed:
  if (motorSpeed > 0)
  {
    myStepper.setSpeed(motorSpeed);
    
    // step 1/100 of a revolution:
    int stepsToTake = stepsPerRevolution / 100;
    
    // Only move if we have not reached the limit
    if (stepCount + stepsToTake < 1000L * stepsPerRevolution)
    {
      myStepper.step(stepsPerRevolution / 100);
      stepCount += stepsToTake;
      int revolutionsTaken = stepCount / stepsPerRevolution;
      display(1000 - revolutionsTaken);
    }
  }
}
Send Bitcoin tips to: 1G2qoGwMRXx8az71DVP1E81jShxtbSh5Hp

Go Up