Using Stepper motors to lift a model bridge
Moderators: adafruit_support_bill, adafruit
Please be positive and constructive with your questions and comments.
- adafruit_support_bill
- Posts: 88086
- Joined: Sat Feb 07, 2009 10:11 am
Re: Using Stepper motors to lift a model bridge
Yes, that should do it.
- roadshark
- Posts: 652
- Joined: Sun Nov 29, 2015 5:53 am
Re: Using Stepper motors to lift a model bridge
I have got two motors set up using the MP6500 driver to test out the code. The code compiles but the motors just sit there and do nothing. I used this code to see if I had everything hooked up properly and it works.
However when it gets to the first part where it stops I thought it would reverse position because of this -300 but it just keeps going forwards.
So I am not sure why my bridge lifting code does not work.
A second issue is that the motors I am using for testing
Electrical parameters
General specification Electrical specification
Step angle 1.8° Rated voltage 3.3V
Number of phase 2 Rated current 1.5A
Insulation resistane 100MΩmin.(500V DC) Resistance per phase 2.2Ω±10%
Insulation class Class B Inductance per phase 5.0mH±20%
Rotor inertia 57g.cm ² Holding torque 450mN.m
Mass 0.24kg Detent torque 15mN.m
Have a rated voltage of 3.3. If I try and run them at this voltage they do not turn. If I increase the voltage to 7 volts they work fine. Is this because I have put a current limit of 1.5 amps and should I be using 7 volts. Here is the bridge lifting code
Code: Select all
// MultiStepper.pde
// -*- mode: C++ -*-
// Use MultiStepper class to manage multiple steppers and make them all move to
// the same position at the same time for linear 2d (or 3d) motion.
#include <AccelStepper.h>
#include <MultiStepper.h>
// EG X-Y position bed driven by 2 steppers
// Alas its not possible to build an array of these with different pins for each :-(
AccelStepper stepper2(AccelStepper::FULL4WIRE, 23, 25, 27, 29);
AccelStepper stepper3(AccelStepper::FULL4WIRE, 31, 33, 35, 37);
// Up to 10 steppers can be handled as a group by MultiStepper
MultiStepper steppers;
void setup() {
Serial.begin(9600);
pinMode (29, OUTPUT);
pinMode (37, OUTPUT);
digitalWrite(29, LOW); //sets the voltage (MP6500)to 1.5 amps motor 1
digitalWrite(37, LOW); // sets the voltage (MP6500)to 1.5 amps motor 2
pinMode(22, OUTPUT);
pinMode(24, OUTPUT);
pinMode(26, OUTPUT);
pinMode(28, OUTPUT);
digitalWrite (22, LOW);// used to set the number of steps quarter/half/full
digitalWrite (24, LOW);
digitalWrite (26, LOW);
digitalWrite (28,LOW);
// Configure each stepper
stepper2.setMaxSpeed(1000);
stepper3.setMaxSpeed(1000);
// Then give them to MultiStepper to manage
steppers.addStepper(stepper2);
steppers.addStepper(stepper3);
}
void loop() {
long positions[2]; // Array of desired stepper positions
positions[0] = 1000;
positions[1] = 1000;
steppers.moveTo(positions);
steppers.runSpeedToPosition(); // Blocks until all are in position
delay(1000);
// Move to a different coordinate
positions[0] = -3000;
positions[1] = -3000;
steppers.moveTo(positions);
steppers.runSpeedToPosition(); // Blocks until all are in position
delay(1000);
}
So I am not sure why my bridge lifting code does not work.
A second issue is that the motors I am using for testing
Electrical parameters
General specification Electrical specification
Step angle 1.8° Rated voltage 3.3V
Number of phase 2 Rated current 1.5A
Insulation resistane 100MΩmin.(500V DC) Resistance per phase 2.2Ω±10%
Insulation class Class B Inductance per phase 5.0mH±20%
Rotor inertia 57g.cm ² Holding torque 450mN.m
Mass 0.24kg Detent torque 15mN.m
Have a rated voltage of 3.3. If I try and run them at this voltage they do not turn. If I increase the voltage to 7 volts they work fine. Is this because I have put a current limit of 1.5 amps and should I be using 7 volts. Here is the bridge lifting code
Code: Select all
#include <Wire.h> // Enable this line if using Arduino Uno, Meg
#include <AccelStepper.h>
#include <MultiStepper.h>
// AccelStepper Setup
AccelStepper stepperLH(AccelStepper::FULL4WIRE, 23, 25, 27, 29);//Left hand motor 23 step, 25 direction, 27 voltage (I1) HIGH, 29 voltage(I2) LOW
AccelStepper stepperRH(AccelStepper::FULL4WIRE, 31, 33, 35, 37);//Right hand motor 31, 33, 35, 37
MultiStepper steppers;
// Stepper Travel Variables
long initial_homing = -1; // Used to Home Stepper at startup
#define home_switch1 10 // Pin 10 connected to Home Switch (MicroSwitch)
#define home_switch2 9 // Pin 9 connected to Home Switch (MicroSwitch)
#define button_BridgeLiftBegin 8 // Pin 8 connected to button to begin bridge lift sequence
#define button_Bridge Lower Sequence 7 // Pin 7 connected to button to begin bride decent sequence
void setup() {
Serial.begin(9600);
// Configure each stepper
stepperLH.setMaxSpeed(100);
stepperRH.setMaxSpeed(100);
pinMode(10, INPUT_PULLUP); //button homing switch 1
pinMode(9, INPUT_PULLUP); //button homing switch 2
pinMode(8, INPUT_PULLUP); //button bridge accent
pinMode(7, INPUT_PULLUP); //button bridge decent
pinMode(25,OUTPUT);// Write this pin LOW to limit current to 1.5 amps
pinMode(37,OUTPUT);//Write this pin LOW to limit current to 1.5 amps
pinMode(22, OUTPUT);// steps
pinMode(24,OUTPUT);//steps
pinMode(26,OUTPUT);//steps
pinMode(28,OUTPUT);//steps
digitalWrite (25,LOW);
digitalWrite (37, LOW);
digitalWrite (22, HIGH); //designates the number of steps
digitalWrite (24, HIGH); //
digitalWrite (26, HIGH);//
digitalWrite (28, HIGH);//
// Start Homing procedure of Stepper Motor at startup
Serial.print("Stepper is Homing . . . . . . . . . . . ");
while (digitalRead(home_switch1)|| digitalRead(home_switch2))
{ // Move motors towards home until both switches are activated
if(digitalRead(home_switch1))
stepperLH.moveTo(initial_homing);// homing switch on this motor should stop both motors
if (digitalRead(home_switch2))
stepperRH.moveTo(initial_homing);// Set the position to move to
initial_homing--; // Decrease by 1 for next move if needed
steppers.run(); // Start moving the steppers
}
stepperLH.setCurrentPosition(0); // Set the current position as zero for now
stepperRH.setCurrentPosition(0);
stepperLH.setMaxSpeed(100.0); // Set Max Speed of Stepper (Slower to get better accuracy)
stepperRH.setMaxSpeed(100.0);
initial_homing = 1;
while (!digitalRead(home_switch1)|| !digitalRead(home_switch2))
{ // Move motors away from home until both switches are deactivated
if(digitalRead(home_switch1))
stepperLH.moveTo(initial_homing);// homing switch on this motor should stop both motors
if (digitalRead(home_switch2))
stepperRH.moveTo(initial_homing);// Set the position to move to
initial_homing++; // increase by 1 for next move if needed
steppers.run(); // Start moving the steppers
}
stepperLH.setCurrentPosition(0);
stepperRH.setCurrentPosition(0);
Serial.println("Homing Completed");
// give stepperLH & stepperRH to MultiStepper to manage
steppers.addStepper(stepperLH);
steppers.addStepper(stepperRH);
}
void loop() {
if (digitalRead (8) == LOW) {//raises the bridge deck
while (digitalRead(8) == LOW);
long positions[2]; // Array of desired stepper positions
positions[0] = 1000;//Maximum elevation of the liftedbridge deck
positions[1] = 1000;//Maximum elevationof the lifted bridge deck
steppers.moveTo(positions);
steppers.runSpeedToPosition(); // Blocks until all are in position
}
if (digitalRead (7) == LOW) {//Lowers the bridge deck
while (digitalRead(7) == LOW);
long positions[2]; // Array of desired stepper positions
positions[0] = 0;//Maximum elevation of the liftedbridge deck
positions[1] = 0;//Maximum elevationof the lifted bridge deck
steppers.moveTo(positions);
steppers.moveTo(positions);
steppers.runSpeedToPosition(); // Blocks until all are in position
}
}
- adafruit_support_bill
- Posts: 88086
- Joined: Sat Feb 07, 2009 10:11 am
Re: Using Stepper motors to lift a model bridge
AccelStepper and MultiStepper are different from the Adafruit motor shield library. The run() function - and all of its variants is not a blocking function. You need to call it frequently and repeatedly for the motors to run.The code compiles but the motors just sit there and do nothing.
As written, I'd expect your code to take one step forward, followed by a 1 second delay, then one step back on each iteration of the loop.
Yea, you need to read between the lines to understand voltage ratings in a stepper motor spec sheet. 3.3v is the maximum DC voltage that will not exceed the current rating. But the motor was never intended to run from a 3.3v supply. Based on the low phase resistance, it was clearly intended to be used with a current-limiting "chopper" driver. Running with a higher supply voltage and active current limiting, you can get higher performance from a small motor without it melting down. There is a detailed explanation of that here:Have a rated voltage of 3.3. If I try and run them at this voltage they do not turn.
https://learn.adafruit.com/all-about-st ... aw-1460534
- roadshark
- Posts: 652
- Joined: Sun Nov 29, 2015 5:53 am
Re: Using Stepper motors to lift a model bridge
Went to the article you suggested to drink from the knowledge tree. "requires a good understanding of both the motor and the controller." I think I am shot!!! Is the driver I am using a '(pololu mp6500) a 'chopper' driver? (I am sure there is a 'pun' somewhere there.) At 7 volts with current limiting at 1.5 amps the motors runs well and are not heating up so I am assuming it is ok to do this.
Now for the code so I need call the run function often Mmmmmm. I will have a go at it.
Thx.
Now for the code so I need call the run function often Mmmmmm. I will have a go at it.
Thx.
- adafruit_support_bill
- Posts: 88086
- Joined: Sat Feb 07, 2009 10:11 am
Re: Using Stepper motors to lift a model bridge
The mp6500 is indeed a 'chopper'. Early versions of current limiting drivers would 'chop' the power when it reached the current limit. More modern chips like the mp6500 are a bit more graceful about it, but the bottom line is that they allow you to get more torque out of the motor without burning it up.
Since you are using the AccelStepper library, I'd recommend getting familiar with the acceleration/deceleration capabilities and making use of them in your model. This will give you a more realistic motion, as well as reducing wear & tear on the system. Just as you cannot accelerate your velocipede from 0 to 40kph in a single pedal stroke without snapping a chain or a tendon, you need a gentle start to get several thousand tons of steel in motion without snapping cables.
Since you are using the AccelStepper library, I'd recommend getting familiar with the acceleration/deceleration capabilities and making use of them in your model. This will give you a more realistic motion, as well as reducing wear & tear on the system. Just as you cannot accelerate your velocipede from 0 to 40kph in a single pedal stroke without snapping a chain or a tendon, you need a gentle start to get several thousand tons of steel in motion without snapping cables.
- roadshark
- Posts: 652
- Joined: Sun Nov 29, 2015 5:53 am
Re: Using Stepper motors to lift a model bridge
On looking at videos of the bridge in action it is a very slow process lifting that steel indeed! I was hoping to use the multistepper library as I thought it would make it easier to run the two steppers simultaneously. I found that the multistepper library does not support acceleration! So would I be able to use the standard AccelStepper library instead? I have gone back and tried to just do 1 stepper motor turn until it hits the home button, then it reverses off the button stops and sets its position at 0 ready for the main loop. In this code the stepper starts moving in ccw direction. When I press the home button there is a slight hesitation then it continues in a ccw direction until I release the button which stops it. I thought it should go cw until the button is released. At the moment it would keep turning against the switch. How do I get it to reverse direction! I thought this code did this. What am I missing here?
Code: Select all
while (!digitalRead(home_switch)) { // Make the Stepper move CW until the switch is deactivated
stepperLH.moveTo(initial_homing);
initial_homing++;
stepperLH.run();
}
Code: Select all
#include "AccelStepper.h"
// Library created by Mike McCauley at http://www.airspayce.com/mikem/arduino/AccelStepper/
// AccelStepper Setup
AccelStepper stepperLH(AccelStepper::FULL4WIRE, 23, 25, 27, 29);
// Define the Pins used
#define home_switch 9 // Pin 9 connected to Home Switch (MicroSwitch)
// Stepper Travel Variables
long initial_homing=-1; // Used to Home Stepper at startup
void setup() {
pinMode(home_switch, INPUT_PULLUP);
// Set Max Speed of each Steppers at startup for homing
stepperLH.setMaxSpeed(200.0); // Set Max Speed of Stepper (Slower to get better accuracy)
// Start Homing procedure of Stepper Motor at startup
while (digitalRead(home_switch)) { // Make the Stepper move CCW until the switch is activated
stepperLH.moveTo(initial_homing); // Set the position to move to
initial_homing--; // Decrease by 1 for next move if needed
stepperLH.run(); // Start moving the stepper
}
stepperLH.setCurrentPosition(0); // Set the current position as zero for now
stepperLH.setMaxSpeed(200.0); // Set Max Speed of Stepper (Slower to get better accuracy)
initial_homing=1;
while (!digitalRead(home_switch)) { // Make the Stepper move CW until the switch is deactivated
stepperLH.moveTo(initial_homing);
initial_homing++;
stepperLH.run();
}
stepperLH.setCurrentPosition(0);
stepperLH.setMaxSpeed(100.0); // Set Max Speed of Stepper (Faster for regular movements)
}
void loop() {
}
- adafruit_support_bill
- Posts: 88086
- Joined: Sat Feb 07, 2009 10:11 am
Re: Using Stepper motors to lift a model bridge
Yes, you can run multiple motors simultaneously with AccelStepper. You just need to call run() on each of the motors. See the example here: http://www.airspayce.com/mikem/arduino/ ... ample.html
In your code above, you are initializing the stepperLH as AccelStepper::FULL4WIRE. That might explain the failure to reverse. With the MP6500 you should be using AccelStepper::DRIVER.
In your code above, you are initializing the stepperLH as AccelStepper::FULL4WIRE. That might explain the failure to reverse. With the MP6500 you should be using AccelStepper::DRIVER.
- roadshark
- Posts: 652
- Joined: Sun Nov 29, 2015 5:53 am
Re: Using Stepper motors to lift a model bridge
GOLD STAR BILL...That was the issue. I am using a 4 wire stepper motor. So this AccelStepper stepperLH(AccelStepper::DRIVER, 23, 25, 27, 29); Can become this AccelStepper stepperLH(AccelStepper::DRIVER, 23, 25); So I would drive I1 &I2 on the mp6500 from the mega pins to regulate the voltage? Because I had a 4 wire motor I thought I had to use the FULL4WIRE command?
Does this command stepperRH.setAcceleration(50.0); also set the deacceleration as it nears the end position?
Does this command stepperRH.setAcceleration(50.0); also set the deacceleration as it nears the end position?
- adafruit_support_bill
- Posts: 88086
- Joined: Sat Feb 07, 2009 10:11 am
Re: Using Stepper motors to lift a model bridge
You are using 4-wire motor, but the MP6500 driver chip is taking care of the low-level control of all the stepping phases. You just need 2 pins to give it a direction and a pulse per step.
And yes, the setAcceleration should automatically take care of deceleration as you approach the target position.
And yes, the setAcceleration should automatically take care of deceleration as you approach the target position.
- roadshark
- Posts: 652
- Joined: Sun Nov 29, 2015 5:53 am
Re: Using Stepper motors to lift a model bridge
thx:) Yes the motor is slowing down. Great! I am converting the 12 volts using a buck converter to 9 volts for the motors however I used jumper wires to supply the current to the motors via the capacitor. I guess the current was a bit much as the jumper wires started to heat up and were very warm and some smoke was seen:( Now lets try for 2 motors and 2 homing switches and some heavier gauge wire!
- adafruit_support_bill
- Posts: 88086
- Joined: Sat Feb 07, 2009 10:11 am
Re: Using Stepper motors to lift a model bridge
What is the purpose of the buck regulator? The MP6500 can handle up to 35v. As long as you set the current limiting appropriately, your motors are safe with the 12v supply.
- roadshark
- Posts: 652
- Joined: Sun Nov 29, 2015 5:53 am
Re: Using Stepper motors to lift a model bridge
I was running them on 12 volts but one of the motors got really warm. Maybe I didn't have the current limit set right. My understanding would be to leave on the mp6500 pin I1 disconnected and driving I2 LOW should give me 1. 5 amps.
- adafruit_support_bill
- Posts: 88086
- Joined: Sat Feb 07, 2009 10:11 am
Re: Using Stepper motors to lift a model bridge
Current to the motor will be the same for any supply voltage above 3v or so. So 9v or 12v will make no difference in heating.
What you can do to limit heating is to use a lower current limit. Since you can control that from your Mega, you can drop the current limit down to 0.5A when the bridge is not moving.
Alternately, you can use the sleep pin to cut all power to the motor. If your bridge is well enough balanced, the natural cogging of the motor should be sufficient to prevent back-driving via the lead-screw.
What you can do to limit heating is to use a lower current limit. Since you can control that from your Mega, you can drop the current limit down to 0.5A when the bridge is not moving.
Alternately, you can use the sleep pin to cut all power to the motor. If your bridge is well enough balanced, the natural cogging of the motor should be sufficient to prevent back-driving via the lead-screw.
- roadshark
- Posts: 652
- Joined: Sun Nov 29, 2015 5:53 am
Re: Using Stepper motors to lift a model bridge
Have now got two home switches. When I run this code the motors do not stop until both switches have been activated. This would cause a problem because if motor LH arrived at homeswitchLH 1st it would keep rotating until turned off by homeswitchrh which would demolish or damage the switch!
On the other side after both switches have been activated the steppers actually stop when they should reverse and continue until the switch is open. The switches have been activated and now the motors should reverse until the switch is open again,
I like your idea of not powering the motors whilst the deck is at the bottom or at the top. I have put the sleep on a pin and will pull it LOW when the bridge is in either of those two positions. When I push the bridgeDeckUp button I would like to make sure the bridge is at the 0 position. How do I get the position checked? So code would start If (digitalRead(bridgeDeckUp)|| (Need to make sure stepperLH & stepperRH ==0)
{
//Turn on the motors
digitalWrite (30, HIGH);// Enables the sleep pin on the MP6500/stepperLH
digitalWrite (32, HIGH);// Enables the sleep pin on the MP6500/stepperRH
stepperLH.setMaxSpeed(100.0);
stepperLH.setAcceleration(50.0);
stepperLH.moveTo(400);//The height the deck moves to.
stepperLH.run();
stepperRH.setMaxSpeed(100.0);
stepperRH.setAcceleration(50.0);
stepperRH.moveTo(400);//The height the deck moves to.
stepperRH.run();
Is the moveTo a blocking code? So it will not turn the motors off until each Stepper is at position 400?
//Turn off motors
digitalWrite (30, LOW);// Disables the sleep pin on the MP6500/stepperLH
digitalWrite (32, LOW);// Disables the sleep pin on the MP6500/stepperRH
On the other side after both switches have been activated the steppers actually stop when they should reverse and continue until the switch is open.
Code: Select all
// Start Homing procedure of Stepper Motor at startup
while (digitalRead(home_switchLH) || digitalRead(home_switchRH))
{ // Move motors towards home until both switches are activated
if (digitalRead(home_switchLH))
stepperLH.moveTo(initial_homing);// homing switch on this motor should stop both motors
if (digitalRead(home_switchRH))
stepperRH.moveTo(initial_homing);// Set the position to move to
initial_homing--; // Decrease by 1 for next move if needed
stepperLH.run(); // Start moving the steppers
stepperRH.run();
}
Code: Select all
while (!digitalRead(home_switchLH) || !digitalRead(home_switchRH))
{ // Move motors away from home until both switches are deactivated
if (digitalRead(home_switchLH))
stepperLH.moveTo(initial_homing);// homing switch on this motor should stop both motors
if (digitalRead(home_switchRH))
stepperRH.moveTo(initial_homing);// Set the position to move to
initial_homing++; // increase by 1 for next move if needed
stepperLH.run(); // Start moving the steppers
stepperRH.run();
}
{
//Turn on the motors
digitalWrite (30, HIGH);// Enables the sleep pin on the MP6500/stepperLH
digitalWrite (32, HIGH);// Enables the sleep pin on the MP6500/stepperRH
stepperLH.setMaxSpeed(100.0);
stepperLH.setAcceleration(50.0);
stepperLH.moveTo(400);//The height the deck moves to.
stepperLH.run();
stepperRH.setMaxSpeed(100.0);
stepperRH.setAcceleration(50.0);
stepperRH.moveTo(400);//The height the deck moves to.
stepperRH.run();
Is the moveTo a blocking code? So it will not turn the motors off until each Stepper is at position 400?
//Turn off motors
digitalWrite (30, LOW);// Disables the sleep pin on the MP6500/stepperLH
digitalWrite (32, LOW);// Disables the sleep pin on the MP6500/stepperRH
- roadshark
- Posts: 652
- Joined: Sun Nov 29, 2015 5:53 am
Re: Using Stepper motors to lift a model bridge
I had a go.... So when I push the button to lift the deck
Code: Select all
void loop() {
If (!digitalRead(bridgeDeckUp) || stepperLH(currentPosition == 0))
{
digitalWrite (30, HIGH);// Enables the sleep pin on the MP6500/stepperLH
digitalWrite (32, HIGH);// Enables the sleep pin on the MP6500/stepperRH
stepperLH.setMaxSpeed(100.0);
stepperLH.setAcceleration(50.0);
stepperLH.moveTo(400);
stepperLH.run();
stepperRH.setMaxSpeed(100.0);
stepperRH.setAcceleration(50.0);
stepperRH.moveTo(400);
stepperRH.run();
//Bridge deck at top so turn off motors.
digitalWrite (30, LOW);// Enables the sleep pin on the MP6500/stepperLH
digitalWrite (32, LOW);// Enables the sleep pin on the MP6500/stepperRH
}
Please be positive and constructive with your questions and comments.