I have a 23KM series stepper motor, which I am controlling with a easyDriver and an Uno. The stepper motor is spinning a reel that has 22 images to display.
I am having trouble figuring out the values to put in the variables 'NumSteps' and 'StepsPerValue'.
The motor, I think, is a 1.8 degree stepper, so I use 'NumSteps = 200', and since I need to have 22 different images on the reel, I use 'StepsPerValue = 9.09'.
Where I get confused is: when I tell it to do 200 steps, it does about 50 more steps than 1 full revolution. I am using AccelStepper, in which I instantiate like, 'AccelStepper stepper(1, 8, 3);'
Could someone school me on the logic misunderstanding?
You want it to do 22 steps?
Do You think Your code could help us?
Autoformat in the IDE and code tags when pasting....
Yes. And initially I thought that when I send 1 through serial, that it would move 9 steps, and that 22 being sent, would make it do almost a full revolution. But it did not work out that way. Since messaging the last time, I found out that if I use the values: 1600 and 72.72, that it works as desired. Not quite sure why, but here is my new code that appears to work. Could someone tell me why I had to 'hack' it in this way? Or any other tips on my code would also be welcomed.
/**
* Arduino Fruit Machine Feature Reel Controller
* Copyright (c) 2018 Playful Technology
*
* Tested with a Saia-Burgess 6-wire 50Ω/ph UFD23N07RAZ18 stepper motor, recovered from the
* top reel assembly of a Bell Fruit "Snakes and Ladders" fruit machine.
* https://www.johnsonelectric.com/en/product-technology/motion/stepper-motors/rotary-stepper-motors
*
* If using an Arudino UNO "CNC shield", heck the following for pin mapping and availability:
* https://wiki.keyestudio.com/Ks0160_keyestudio_CNC_Shield_V3
* https://blog.protoneer.co.nz/arduino-cnc-shield-v3-00-assembly-guide/
*/
// DEFINES
// The total number of steps required for one complete revolution of the motor
// Common values for motors are:
// - 7.5° step angle = 48 steps
// - 1.8° step angle = 200 steps
#define NUM_STEPS 1600
// There are 12 different values on the reel - numbers 1-12. So, define the number
// of steps between each value as NUM_STEPS / 12.
// For 20 values on a reel with 200 steps, STEPS_PER_VALUE 10 etc.
#define STEPS_PER_VALUE 72.73
// INCLUDES
// Not strictly necessary, but the AccelStepper library provides nice utility functions for acceleration/deceleration
// See: http://www.airspayce.com/mikem/arduino/AccelStepper/
#include <AccelStepper.h>
// CONSTANTS
// The sensor sends a HIGH signal when it is blocked, which occurs when the 12 is facing the front
const byte sensorPin = 2;
// GLOBALS
// If using a motor driver (e.g. L298N), use FULL4WIRE constructor specifying pins A1, A2, B1, B2
// AccelStepper stepper(AccelStepper::FULL4WIRE, 7, 8, 9, 10);
// If using a stepper driver (e.g. A4988), use DRIVER constructor with stepPin, dirPin
AccelStepper stepper(1, 8, 3);
// The number on the reel that we'd like to display
int targetValue;
bool homed = false;
bool isHigh = false;
int detectState = 0;
int counter = 0;
unsigned long timeOfLastHigh;
unsigned long timeOfFirstHigh;
unsigned long lengthOfHigh;
unsigned long lengthsRecorded[24] = {};
int bigCount = 0;
bool lastWasBig = false;
// Initial setup
void setup() {
// Start a serial connection
Serial.begin(115200);
Serial.println(__FILE__ __DATE__);
// Note - if using a CNC shield, the stepper drivers need to be enabled. Sometimes, the enabled pin is automatically
// pulled to ground by a jumper but, if not, write a LOW signal to the enable pin.
pinMode(6, OUTPUT);
digitalWrite(6, LOW);
// Set the sensor pin as an input
pinMode(sensorPin, INPUT);
// Stepper motor speed (steps/sec) and acceleration (steps per second^2)
stepper.setMaxSpeed(20000);
stepper.setAcceleration(8000);
for(int i=i;i<1000;i++){
stepper.runSpeed();
}
CalibrateReel();
}
void CalibrateReel(){
Serial.println("Calibrating");
// Set the stepper to a slow speed
stepper.setMaxSpeed(50);
// Make at most one complete rotation from the current position
stepper.move(1800);
// Advance one step at a time until the sensor is obstructed
while(homed == false){
//Serial.println("inside of !homed");
stepper.run();
detectState = digitalRead(sensorPin);
if(detectState == 1){
if(isHigh == false){
timeOfFirstHigh = millis();
isHigh = true;
}
}
if(detectState == 0){
if(isHigh == true){
timeOfLastHigh = millis();
isHigh = false;
lengthOfHigh = timeOfLastHigh - timeOfFirstHigh;
if(lengthOfHigh > 1000){
if(lastWasBig == true){
bigCount++;
if(bigCount == 2){
homed = true;
bigCount = 0;
}
}else{
lastWasBig = true;
}
}else{
lastWasBig = false;
}
}
}
}
// Stop the motor and declare this the zero position
stepper.stop();
stepper.setCurrentPosition(0);
// Now that calibration is complete, set faster normal motor speed
stepper.setMaxSpeed(20000);
}
void loop() {
// Test whether any input has been received on the serial connection
if(Serial.available() > 0){
// Read any integer sent
homed = false;
targetValue = Serial.parseInt();
// Sending 999 re-calibrates the reel
// (don't use 0 as that is the value parseInt() returns from reading, e.g. a linebreak)
if(targetValue == 999){
CalibrateReel();
return;
}
// A little debug
Serial.print("Now going to:");
Serial.println(targetValue);
// We subtract the result from NUM_STEPS because the reel labels increase anti-clockwise rather than clockwise
stepper.moveTo(STEPS_PER_VALUE * targetValue);
}
// This gets called every frame, and processes any movement of the stepper as necessary
stepper.run();
}
I am assuming that the accelStepper library uses 1/8 microstepping as default, but I had imagined that my NumSteps declaration was telling it otherwise. Still, I would welcome any input on my existing code. Soon I will be adding 4 more reels and opto-sensors to control, and will need to be as efficient as possible to have them all run seamlessly.
Why?
Are You sure this is doing what You want?
unsigned long lengthsRecorded[24] = {};
Uncertain about accelstepper I wonder about this line AccelStepper stepper(1, 8, 3);
I hope the first parameter, being 1, does NOT direct action to pin 1, D1. D0 and D1 is used by serial communication.
I suggest You make a test version of the code. Let it just make the stepper rotate using the lib. Skip serial and all other action. Just make the stepper move using a minimum number of lines in loop.
The AccelStepper doesn't know anything about microsteps. It only knows about 'steps' no matter what the driver will do.
The first parameter defines the type of the connected driver. '1' means a driver with a step/dir input. Other types are e.g. H-bridges with 2 or 4 inputs or drivers for unipolar steppers.
The AccelStepper library also has names for these types, that could be used instead of the magic numbers e.g. AccelStepper::DRIVER or AccelStepper::FULL2WIRE
Thanks!
I actually had used that array to be able to read out calibration data. Then I took it out of the function. I probably should have not included that function in the post.
I actually think that the driver has something to do with the easyDriver that I am using, concerning the microsteps.
If the driver is set to microsteps, then it needs more steps to do one revolution. E.g. if your stepper needs 200 steps in full step, than it needs 1600 steps for one revolution if your driver is set to 1/8 microsteps.
Bad news: You can't make a 200 step per rev motor turn 1 / 22 of a circle, you need a 10:11 gear or cog belt ratio. With a 10 tooth gear on the motor and an 11 tooth gear on the reel, turning the motor 10 steps (18°, 1 / 20 turn) would turn the reel 1 / 22 turn (16.3636363636°).
360° / 16.3636363636° = 22.
Good news. Create a 22 element array containing the best approximation to the serie n * 22/360, n? 0 ..21. Use that array for stepping.
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.