To be used in a spin the wheel-type of game where it has to point to a score accurately. I'm using a motor driver to got it work with Arduino, with this code that decides to rotate or stop with a push button while recording its angle position:
When I divide it into 8 positions, the stepper motor works accurately. But the spin the wheel needs more than 8, 32. When I try to divide it by more than 8 (e.g. 12 or 16), it becomes inaccurate.
Are there any ways to correct that and make the stepper motor accurate for 32 positions? Like if the motor driver should be replaced with other device to control the stepper motor, or that there are better alternatives than stepper motor?
Such a picture is completely useless. We need technical data of the motor. What driver are you using? And what is 'accurately'? Within 1degree? 1/10 degree? A schematic and a picture of your layout would be helpful too.
Using a library for the stepper like my MobaTools would be more easy.
Not yet, it'd give different results then? (though dunno if there are Library examples that are used with motor drivers like below, or it can work with these as well?)
So it's not impossible that these type of correct motor driver (or you refer to other motor board?) can give accurate division for like 32 position? Because so far from what I know, the motor steppers only got accurate when it's controlled by arcade machine-default PCB that strongly holds the motor in 1 of the 32 positions.
For this one, how it can be implemented in my code? So far, without incrementing, I'm doing it like this (accurate with 8 position, inaccurate with 12 position):
You use a way of coding that I will not try to understand.
Use more of Serial.print of key variable, and serial monitor.
This looks dangerous to me. The compiler might think like this: an integer will have a value from an integer divided by a float.
Use absolut positions and not increment like You do in this code.
I have made, and I use a build that either works in angle mode or step mode == steps per turning the table 360 degrees. This controls a rotating table on a mill.
For Your situation I would use step mode, 8 steps, 12 steps, 13 steps, 17 steps.....
Because I have a working code I can post it if you want.
The code is built for future functions/modes not having any final code yet.
Look for the Step mode logic. Lots of micro step is used.
#include<arduino.h>
//I2C for LCD
#include <AccelStepper.h>
#include <Wire.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>
hd44780_I2Cexp mylcd; // declare lcd object: auto locate & config exapander chip
// LCD geometry
#define LCD_COLS 16
#define LCD_ROWS 2
boolean state, old_state;
byte mode = 0; //// 0 = Antal sidor, 1 = vinkel per steg
int faces = 4;
unsigned long nrOfStepsPerRev = 90L*200*4; // microstep 4
void setup() {
Serial.begin(115200);
//1Hz 90% dutycycle
pinMode(9, OUTPUT); // Set digital pin 9 (D9) to an output
TCCR1A = _BV(COM1A1) | _BV(COM1A0) | _BV(WGM11); // Enable the PWM output OC1A on digital pins 9 and invert output
TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS12); // Set fast PWM and prescaler of 256 on timer 1
ICR1 = 62499; // Set the PWM frequency to 1Hz: 16MHz/(256 * 1Hz) - 1 = 62499
OCR1A = 6249; // Set the duty-cycle to 10%: 62499 / 10 = 6249
pinMode(10, OUTPUT); // 1 Hz pulse output on digital pin 9 (D9)
pinMode(13, OUTPUT); digitalWrite(13, LOW);// Make board LED go off
delay(10);//allow pwm timers to start
int status;
status = mylcd.begin(LCD_COLS, LCD_ROWS);
if (status) // non zero status means it was unsuccesful
{
status = -status; // convert negative status value to positive number
// begin() failed so blink error code using the onboard LED if possible
hd44780::fatalError(status); // does not return
}
mylcd.clear();
// Print start message to the LCD
mylcd.print("221101a Rotating");
delay(5000);
mylcd.print("Running");
delay(1000);
}
// The loop function is called in an endless loop
void loop()
{
boolean cmd = readButtons();// + - Go Chg mode
if (( millis() % 1000 ) > 499 )
{
state = true;
}
else
{
state = false;
}
if( state) { //update twice per second;
if( mode == 0) //number of surfaces
{
switch (cmd)
{
case increase:
{
faces++;
brake;
}
case decrease:
{
faces--;
if (faces < 1) faces = 1; //1 rotate one turn
brake;
}
case Chg:
{
mode = 1; //switch to angle mode
// goFlag = false;//
brake;
}
case Go:
{
AccelStepper(anglePos);
anglePos += nrOfStepsPerRev * 360 / faces;
brake;
}
default:
brake;
}
if(goFlag)
{
AccelStepper(anglePos);
}
}
else if ( state == 1 ) // Angle per step
{
}
}
}// End of loop
Problem is 200 steps is not evenly divisible by 12, one twelfth of 200 is 16 and two thirds (16.6667), you can't do 2/3 of a step.
You can do 16 steps (28.8°) or 17 steps (30.6°), but not 30° ( 1/12 of 360).
That's the reality. Approximations will take place but using the proper algorithm the position will not drift.
Using micro stepping the error can be made smaller. For my rotating table the resolution is 1 to 576 000 corresponding to, I think, 0.24 seconds.
No video is needed to se the trouble with Your code. When not even the theory is correct no code can fix it.
You told about 8 or 12 stops per rev. 8 worked but not 12.
There will always be numbers of steps that will not precisely match a stepper motor.