Linear actuator wit...

Clear all

# Linear actuator with DM542, 28BYJ-48, and Arduino

23 Posts
3 Users
0 Likes
4,849 Views
(@bball-auto)
Member
Joined: 3 years ago
Posts: 13
Topic starter

Hi Dronebot Community.  I’m really glad to have found you.

I am a newbie to driving motors (and Arduinos for that matter).  Below is a drawing depicting my basic setup.  I wish to drive a carriage on a 1.5-meter belt driven linear actuator using a bipolar NEMA23 stepper motor.  The intended motion is extremely simple.  I wish to have the carriage start at one side (or end) of the ∆Ltot and as quickly as possible transition to a constant speed toward the other side of the ∆Ltot.  I hope to move the NEMA23 at the higher end of its reasonable speed range, so I assume that an acceleration and deceleration distance is a good idea, though I hope to keep that distance as small as possible to maximize the length of my ∆LConstantSpeed.  I would like to trigger the NEMA23 “carriage slide” back and forth from one side to the other with a reliable button #1.

On top of the carriage is a 28BYJ-48 bipolar.  This stepper only needs to perform a very simple 180° rotation upon the push

of a reliable button #2.

Here is a summary of the sequence I hope to achieve:

1. Initial Position: Positioned at left most position or right most position.  Doesn’t matter which.
2. Action 1: Upon pushing Button #1, NEMA23 drives carriage to the other side at constant speed with smallest possible acceleration/deceleration periods.  I am assuming this movement can easily be stopped by programming in a certain number of turns of the motor.
3. Action 2: Upon pushing Button #2, 28BYJ-48 rotates 180°.
4. Action 3 Upon pushing Button #1, NEMA23 drives carriage to the other side at constant speed with smallest possible acceleration/deceleration periods.  I am assuming this movement can easily be stopped by programming in a certain number of turns of the motor.
5. Action 3: Upon pushing Button #2, 28BYJ-48 rotates 180°.
6. Repeat as needed

Here are the control components I’m hoping to use.

• NEMA23: Bipolar stepper motor, (4 lead) 2.8 Amp per phase, 1/8° per step, https://openbuildspartstore.com/nema-23-stepper-motor/
• DM542 to drive the NEMA23
• Arduino Uno or Mega2560 to drive the DM542
• 28BYJ-48 bipolar stepper
• ULN2003 driver board to drive the 28BYJ-48 (unless someone has a better idea). Hopefully, the Uno or Mega will be able to drive both the DM542 and the ULN2003????
• A reliable set of buttons (for my application, I prefer them to be a push buttons, but ones that are reliable without bounce issues)

Other considerations.

• I have considered placing position sensors at either end of the ∆Ltot but do I need them? How likely is it that the NEMA23 will get off sequence and require position sensors to set a home and stop?
• Same position sensor question for the 28BYJ-48. How easy is it to keep a “home position” without a homing sensor?
• I need to figure out how to mount the wiring for the 28BYJ-48 on the carriage. Is it possible to power and control the ULN2003 with a battery on the carriage and wirelessly send the signal from the Arduino for the 28BYJ-48 to perform the half turn?  Would this be easier than creating some flex wire assembly to allow the control wiring to move through ∆Ltot as the carriage moves?
• I need the speed to be defined and repeatable for this application, so making speed adjustments via a potentiometer scares me. I need to make speed tweaks via changing something in the sketch so I can know exactly how repeatable I am…  I’m assuming that is fairly easy to do.

I really appreciate any help you folks can offer this old engineer.  Although I’ve been able to successfully mimic various sketches (such as

), knowing the simplest method to accomplish this is out of reach for me right now.  I might as well admit that the accelstepper library and the various IDE code is daunting to me.  Ultimately, I want to be able to design much more complex automation.  The electronics and design of automation doesn’t scare me at all… the control software does.  Thanks much for any guidance! B

Topic Tags
(@will)
Member
Joined: 3 years ago
Posts: 2526

Wow! That's a lot to cover.

Your overall goal seems pretty reasonable. I think you'd be better using limit switches then a step count for positioning. You'll probably need one at one end of the rail anyway for homing purposes, adding a second one should be quite straightforward. Having (normally open) limits at both ends will eliminate any problems during operation if the belt should slip (or skip teeth).

Whether you'll need any acceleration probably depends most on the speed you hope to achieve and the mass of the driven carriage. If it's light then you may not need to specify acceleration at all. But bear in mind that the belt's elasticity will provide some lag in starting and stopping the carriage.

You say the 28BYJ "rotates 180". Does it need to turn both times in the same direction or does it just turn back to it's original position. If it only needs to go 180 degrees and can return by rotating backwards to its original position, then you may be able to use a servo which will only use 1 Arduino pin instead of the 4 (IIRC) that the ULN would require. Besides, servos are self-homing.

You might consider using a drag chain to hold all of the wiring neatly. This would avoid any potential for RF interference when using the machine.

As for buttons, I'd suggest using easily available (i.e. cheap) switches and googling "switch bounce" to see a range of ideas about how to make them as reliable as possible.

I would recommend using the accelstepper library to manage your NEMA23. You can set the speed as a constant (after experimenting to find the best value) and you won't need a potentiometer. Note that I've never used a DM542 stepper driver.

(setup)

- rotate servo to 0

- while limit switch is not closed {step left} // move carriage to left until it closes the limit switch

- while limit switch is closed {step right} // Move carriage so it's not using the switch closed

- set direction leftToRight (either LOW or HIGH)

- set targetStepCount = 1000000 (move to this count or until limit switch hit)

(end setup)

(loop)

doLimitSwitch();

if (button1) { ... do whatever ...}

if (button2) {do whatever}

take a step in the current direction

(end loop)

- void doLimitSwitch()

if (limit switch is down) switch direction; step until switch is no longer closed; set targetStepCount=-targetStepCount (i.e. reverse target position)

(end doLimitSwitch)

I hope this gives you a bit more structured view of your project. Break it down into parts and work on each one separately. I'd suggest starting with the switches, as they'll be the easiest components to get and play with.

Once you have them working, move on to the servo (or 28BYJ). The servo will be the next easiest part to integrate (however, the 28BYJ will probably be the hardest).

Then, after you've built up some confidence with that, move on to the NEMA23 and the accelstepper library. Once you wrap your head around the library you'll wonder why you were ever afraid of steppers.

And always ask in the forum if you have anything you can't figure out.

Anything seems possible when you don't know what you're talking about.

(@bball-auto)
Member
Joined: 3 years ago
Posts: 13
Topic starter

@will

Thanks much for the ideas.  I'm able to devote some time to this immediately.  Some questions before jump on the attempt:

1. Regarding your recommendation to use limit switches - Is this because of inherent difficulty of keeping stepper position over the long haul?  I had assumed it would be easy to lose position, but i'm naive on the topic.

2. Limit switch - do you have a recommendation on what type would work well with this linear actuator?

3. Regarding acceleration - noted about the inherent flex in the belt.  The carriage should be really light so fingers crossed i won't need accel and decel.

4. Regarding the 28BYJ - it only needs to 180 and then return to original position.  super point on the servo, though i don't have any of them...  i'm sure i could have one here quickly.  Any suggestions on one to try?  it's a super light item it will be turning.  I predict the load will be 20 to 30 grams sitting on top of the motor sitting on the carriage.

5.  Drag chain -  thanks for the suggestion!  I'll try to study how to set one up.

6. Regarding code - that's the hard part for me - This coding is just such a new thing for me - i'm hoping it will all start to make sense.  I'll have a go with what you've mentioned.  I was just able to create my first movement using an accelstepper sketch example.  Fingers crossed i can figure it out.   But until i get it figured out, any suggestions on what to use in the code rather than limit switches?  I'd like to try to get this moving today and don't have limit switches to play with right now.

I am hoping right now to first figure out how to use code to get the NEMA23 moving a certain # of rotations in one direction, then back the same in the other direction on a button push so i can actually hook up the motor in the linear actuator rig to actually try it out.  i could start with a super small number rotations to ensure i don't damage the rig by driving it into a stop by accident.

(@will)
Member
Joined: 3 years ago
Posts: 2526

@bball-auto

1) I don't absolutely trust step counts because of potential slipping or skipping of the teeth on the belts as  the belt changes size with temperature and age. if you home the carriage on each left (or right) passage then the errors should be minimal.

2) Pretty much any type available will work. I just get mine from Amazon (more expensive than eBay but available months faster)

4) You'll have to pick the servo based on the effort it'll take to perform whatever task. I usually use 9g servos but usually I'm just lifting a pen off paper.

5) They're easy to set up. You just pass all the wiring through them, glue one end near your control box and solder (or use a screw terminal to connect) to your Arduino and controller(s). Then glue the other end to the carriage and attach the wires to whatever's on the carriage. I usually hot glue the chain down from the control box to about halfway down the carriage rail. Look for a picture and you'll immediately grasp the concept.

6) Look for examples for the components you'll be using. Load the examples onto your Arduino and play with them, changing values to see how that alters the effect (and what stops it from working). When you feel comfortable with it, merge the parts of it into you project's software and get it working piece by piece. It will be confusing at first, but you'll soon learn how to mere the parts together.

Your first project code will probably look like a dog's breakfast, but you can learn how to separate out common code into callable subroutines and functions to reduce both the size and complexity of the code.

PS

To test the NEMA, move the carriage to the middle of the rail. The order in which the NEMA wires are connected to the driver may cause CW and CCW to be in the opposite direction that you expected. Starting from the middle means you'll have lots of time to react if it moves in the "wrong" direction.

Once you get your NEMA23 code working with numbers, you can then "simulate" the effect of the limit switches by just using two regular pushbuttons. Just push the appropriate one as the carriage is moving.

Anything seems possible when you don't know what you're talking about.

Member
Joined: 4 years ago
Posts: 340

@bball-auto

@will gave you some really good advice.

Drag chains can be 3D printed but they will not be as ridged or work as well as ones you can buy. They also have to be longer than you think you need(The bend radius to turn around plus coupling hardware that usually does not bend). The ones I have printed work great but they sag a good amount. If your chain will be resting on a table or the like below it, that is not even an issue. Some designs are better than others but I have yet to find one that competes with the manufactured ones.

Limit switches work great. Usually on an interrupt to reset your position to 0. But in 3D printers and CNC machines, they usually hit, back off and come back at a slower speed. This is for accuracy. You want the least amount of energy when detected(inertia and stretch on the belt can add or take away form this). Stretching the belt can store energy and give you an inaccurate position so the least amount of tension is optimal here. You also have the option of using a hall effect sensor. It will detect before the limit point and you can program in the process of homing automatically(or at least reduce the speed to get a more accurate position as it gets close).

Acceleration and deceleration periods would reduce the stretch and slippage on the belt. Considering it is only 1 meter, I don't know how that would look like on this.

(@bball-auto)
Member
Joined: 3 years ago
Posts: 13
Topic starter

Thanks much for the thoughts and help.  My regular responsibilities have kicked me off this side project more than I’ve wanted but I’ve been able to find a bit of time to tinker and have learned a good bit.  First off, after thinking about the entire project, I’ve decided to start by concentrating on the left to right movement.  I can place the servo on top of the carriage at a later date.  I’ve found a really simple sketch to imitate.  I want to give the author kudos - https://www.makerguides.com/tb6600-stepper-motor-driver-arduino-tutorial/ .  I liked the simplicity of his starting circuit.  I created a sketch that based on his second example to control rotation, speed and direction.

Here is a drawing of my setup:

Here is the code that is working:

/* This sketch started from a copy of "Basic_TB6600_Rot_Speed_Dir" which came from sketch #2

*/

#define dirPin 2

#define stepPin 3

#define stepsPerRevolution 400

void setup() {

// Declare pins as output:

pinMode(stepPin, OUTPUT);

pinMode(dirPin, OUTPUT);

}

void loop() {

// Set the spinning direction clockwise:

digitalWrite(dirPin, HIGH);

// Spin the stepper motor 3 revolutions fast:

for (int i = 0; i < 3 * stepsPerRevolution; i++) {

// These four lines result in 1 step:

digitalWrite(stepPin, HIGH);

delayMicroseconds(300);

digitalWrite(stepPin, LOW);

delayMicroseconds(300);

}

delay(2000);

// Set the spinning direction counterclockwise:

digitalWrite(dirPin, LOW);

// Spin the stepper motor 3 revolutions fast:

for (int i = 0; i < 3 * stepsPerRevolution; i++) {

// These four lines result in 1 step:

digitalWrite(stepPin, HIGH);

delayMicroseconds(300);

digitalWrite(stepPin, LOW);

delayMicroseconds(300);

}

delay(2000);

}

I’ve been comfortable enough with the performance of this sketch testing it on the solo motor that I went ahead and hooked it up to my linear actuator and carefully tried it.  I’m pleased that I likely do not need to setup and acceleration and deceleration period.  You guys were right… there appears to be enough elastic energy in the system to keep the back forces to a reasonable level upon movement and stopping of the carriage.  I now know how to alter the distance of the carriage traverse and I know how to alter the speed.  The image below shows my rig on a 1m linear rail.  What I would like to do next is create code in the sketch that triggers the carriage traverse upon pushing a button.  Could you help me with what code to you and where to put it in this sketch?

I’m assuming I will need a button wired in to the Arduino 5V that is in pull up or down configuration input to one of the Arduino digital outputs.  I’m guessing that I could take a pull up or down button and plug it into one of the digital outputs like Bill did in

.

Is that what you suggest?

I appreciate any help!

(@will)
Member
Joined: 3 years ago
Posts: 2526

@bball-auto

Since you aren't using a library for the stepper motor, I'd suggest collecting all of the code to move the stepper into a subroutine. That way you'll only need to call the sub instead of duplicating code all through your program.

So, make a subroutine which takes in the direction to turn and the delay after powering the drive pins

void takeAStep( int direction, int speed )

{

digitalWrite(dirPin, direction);

digitalWrite(stepPin, HIGH);

delayMicroseconds(speed);

digitalWrite(stepPin, LOW);

delayMicroseconds(speed);

}

So now whenever you need to move a step you just call this with the direction and it'll move one step in the desired direction.

Declare a pin to use for your (pretend) limit switch. You won't need to worry about bounce too much because the carriage direction will be reversed as soon as the switch reads LOW, so it doesn't matter if it bounces back to HIGH or not.

It looks like your diagram show you using pin 2 for the switch. You need to connect one switch contact to GND and the other contact to pin D2 (doesn't matter which end goes where). Do NOT connect any part of the switch to the stepper driver !

#define limitPin 2

in setup()

set pinMode(limitPin,INPUT_PULLUP);

To test the takeAStep subroutine, change loop as follows

void loop() {

// Set the spinning direction clockwise:

// Spin the stepper motor 3 revolutions fast:

for (int i = 0; i < 3 * stepsPerRevolution; i++) {

takeAStep(HIGH,300);

}

delay(2000);

// Set the spinning direction counter clockwise:

// Spin the stepper motor 3 revolutions fast:

for (int i = 0; i < 3 * stepsPerRevolution; i++) {

takeAStep(LOW,300);

}

delay(2000);

} // end loop

This should pretty much duplicate your present code, but will illustrate the advantage of using a subroutine to eliminate all the duplicated code  for stepping.

The parameter direction will tell the sub which direction to apply to the dirPin and the speed will allow you to control the length of time that the pulses are applied in case you need to change speed.

Please test this code to make sure that I haven't oopsed anything important and try adjusting speed and step counts (like 4 revolutions) and examine the code to see how and why it works.

When this is working properly and you understand what's going on, then we'll move on to simulating the limit switches.

Anything seems possible when you don't know what you're talking about.

(@bball-auto)
Member
Joined: 3 years ago
Posts: 13
Topic starter

@will

thanks much for the code.  i'll try it.

when it comes to the code, i've pretty much been grasping at straws because with my limited time i have not found something simple to read to explain IDE coding.

It seems to me that the libraries (stepper and accelstepper) are mix and match puzzle pieces - i'm not at the point where i even see the code big picture to put in the various pieces.

What do you think is the most basic IDE code primer?  perhaps i need to just take the time and read and play.

I really appreciate your help and patience!

(@will)
Member
Joined: 3 years ago
Posts: 2526

Posted by: @bball-auto

@will

when it comes to the code, i've pretty much been grasping at straws because with my limited time i have not found something simple to read to explain IDE coding.

It seems to me that the libraries (stepper and accelstepper) are mix and match puzzle pieces - i'm not at the point where i even see the code big picture to put in the various pieces.

What do you think is the most basic IDE code primer?  perhaps i need to just take the time and read and play.

You can try Googling for introductions to C++ which is the normal language for the IDE. That will help you understand the basics of the language syntax and value addressing an storage.

The libraries are indeed mix and match pieces, but they aren't really puzzles. The C++ language is based on the procedural language C and the ++ indicates that it has been modified to be an "object" language. That means that the data and commands (usually called methods) are all stored in the same bundle.

So, some very talented people take a device like a stepper motor and write code to take user input and manipulate the device. So, for instance you tell it what type of motor and what pins to use and it initializes and instance of the object ready to go. Mainly this  saves everybody from having to learn all of the nitty-gritty esoterica of the device and provides a ready means of using it with simple commands.

I don't know of any simple, guaranteed primer for the IDE. If you're starting with no programming background, than you should read up on C and C++ to get familiar with the basics of the language. If you already have some understanding of the language, then take simple devices (like buttons) and just play with the examples. Try to understand how the Arduino sees them and try changing the pins and code to see what happens.

When you look at libraries, check out both what values are stored inside it and what methods it provides to control the device.

And if you have questions, ask here. There are lots of people to answer them.

Anything seems possible when you don't know what you're talking about.

(@bball-auto)
Member
Joined: 3 years ago
Posts: 13
Topic starter

@will, thanks for hanging in there with me.  I took a few hours, took some deep breaths and just read the stepper and stepper excel library pages.  I created a sketch that is working and would love to figure out how to code a button press to initiate (location in bold at the start of the void loop section).  Any ideas on how to code in a button to initiate that movement back and forth?

here is the sketch:

/* Going to use the stepper library with most basic back and forth. Right now i'm using a delay, but hope
* to move next to using a button to initiate move in one direction with delay that then comes back home to wait
* for next button push.
* Using the 2 wires setup w DM542 and UNO (pulse+ to Dig 3, Direction+ to Dig 2)
*/

#include <Stepper.h>

//Creating a variable (perhaps the IDE vernacular is something else) that defines the number of steps per revolution

const int stepsPerRev = 1600;

//Going to define a variable for the number of full turns to make
const int numRevs = 5;

// i'm using format from example sketches from stepper library & setting pin 2 & 3
//
Stepper myStepper = Stepper(stepsPerRev,2,3);

void setup() {
// Setting speed in RPMs
myStepper.setSpeed(250);

}

void loop() {

// I hope to insert a trigger to start this first rotation based on a button push here

// First let's go one loop in one direction:
myStepper.step(numRevs * stepsPerRev);
delay(5000);

// Now the other direction;
myStepper.step(-numRevs * stepsPerRev);
delay(5000);

}

Side note, this was actually fun to think through this and finding some logic.  i think that's been the hard part.  physics, thermodynamics, electromagnetics - those are logical and easy to understand when you can read and logically think through it...  this coding stuff was kicking my butt till i chilled out and just read.  I'm thankful for the patience you guys have shown me!  i've a ways to go for sure.

(@will)
Member
Joined: 3 years ago
Posts: 2526

@bball-auto

First, you'll notice that the documentation for Stepper:steps() says that it's a blocking function. That means that when you call it it will not return to your loop to execute any more of your commands until it's finished executing all of the steps you requested.

That's not what you want, you need to be able to check the switches between steps. So you should change your code to something like:

long  stepCount=0, maxSteps = numRevs*stepsPerRev;

int  direction=1; // moving to the right  -1 is moving to the left

in loop ()

while (stepCount<maxSteps) {

myStepper.step(1) ;

stepCount++;

if (stepCount==maxSteps/2)

Serial.println("Half way right");

}

while (stepCount>0) {

myStepper.step(-1);

stepCount--;

if (stepCount==maxSteps/2)

Serial.println("Half way left");

}

This breaks it out so that we only take 1 step at a time and can check the state of anything between steps. We're not locked out as we would be if we put the entire count of steps in the call to  myStepper.step().

This is important, because we need to see if the carriage servo has to be moved and then issue an order to it "between steps".

When you feel comfortable with that, we'll talk about how to use a regular pushbutton to simulate limit switches and then how to send the carriage back and forth, reversing direction whenever a limit switch is hit.

Hint: whenever we move 1 step in the + or - direction, we can use a variable, say dirn, to be +1 or -1 and this direction will be reversed whenever either limit switch is closed.

Anything seems possible when you don't know what you're talking about.

(@bball-auto)
Member
Joined: 3 years ago
Posts: 13
Topic starter

@will

i'm not sure i want to use limit switches anymore. i may be ok with the setup i've currently got (without sensors at the end) as long as i can start the sequence of back and forth with a pushbutton.

is there a simple way to put in a pushbutton to start that first movement?

(@will)
Member
Joined: 3 years ago
Posts: 2526

@bball-auto

If you (manually) push the carriage over to the left edge you want to start from, then you can probably just begin from the moment of power on; no need for a button to start the carriage. I'd have the Arduino delay a couple of seconds at the end of your setup() to let all the circuits stabilize and then just start stepping away.

You will first want to make a mark so that you will always position the carriage to the same starting point every time, and you'll also need to make an accurate count of the steps from your starting point to your turn-around point.

All you'll need to do is start off with step count zero (leftmost position) and step until you get to your turn-around point and then start stepping back until you get to zero.

Then we'll get to the servo button(s).

Anything seems possible when you don't know what you're talking about.

(@bball-auto)
Member
Joined: 3 years ago
Posts: 13
Topic starter

@will

i'd prefer to have a button to start the sequence.  do you know how i would add one in that spot?  Thanks

(@will)
Member
Joined: 3 years ago
Posts: 2526

@bball-auto

I don't understand what you mean by adding a button "in that spot" ? What spot do you mean ?

Anything seems possible when you don't know what you're talking about.

Page 1 / 2