Running a stepper motor with smooth rotation

Hi,

I have NEMA Hybrid Stepper motor, I am using a M542T driver to drive the stepper motor with Arduino Uno. I have LCD displaying the count of the rotation. I programmed the to achieve 1600 steps delivering 100 RPM. So for every 1600 step it will count and display the count on a LCD. The PWM on off time i calculated as 365 micro second for the stepper. The code execution time for LCD is 24 milli seconds. So after every 1600 steps the motor stops for a few millisecond and the starts. So the rotation is not smooth at all.

If there is a way for me to overcome the problem please help me.

Thanks in advance.

My Sketch:

#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_TFTLCD.h> // Hardware-specific library

#define LCD_CS A3 // Chip Select goes to Analog 3
#define LCD_CD A2 // Command/Data goes to Analog 2
#define LCD_WR A1 // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0

#define LCD_RESET A4 // Can alternately just connect to Arduino’s reset pin

// Assign human-readable names to some common 16-bit color values:
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
#define BLUE 0x3498DB
Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
//Variable Initialization
int i = 0;
int a = 0;
int b=0;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial.println(F(“TFT LCD test”));

uint16_t identifier = tft.readID();
tft.begin(identifier);
pinMode(10, OUTPUT); // Step Pin
pinMode(11, OUTPUT) ; // Dir Pin
digitalWrite(10, LOW);
digitalWrite(11, LOW);

tft.setRotation(1);
tft.fillScreen(BLACK);
unsigned long start = micros();
tft.setCursor(90, 0);
tft.setTextColor(BLUE);
tft.setTextSize(4);
tft.println(“SENTIAL”);
tft.println();
tft.setTextColor(GREEN);
tft.setTextSize(3);
tft.println(“Operation Mode: 3”);
tft.println();
tft.println();
tft.setTextColor(RED);
tft.setTextSize(3);
tft.print(“Rate:”);
}

void loop() {

// put your main code here, to run repeatedly:

i = i + 1;
digitalWrite(10, HIGH);
delayMicroseconds(375);
digitalWrite(10, LOW);
if(i<1600)
{
delayMicroseconds(375);
}
if (i == 1600)
{
b=displayRate(b);
}
}

int displayRate(int a)
{
a = a + 1;
tft.fillCircle(126, 136, 40, BLACK);
tft.setCursor(96, 134);
tft.print(a);
i = 0;
return a;
}

i is incremented each time through the Loop. If it is less than 1600, it waits 375ms, if it is exactly 1600, it does the LCD which takes 24ms... Shouldn't you then wait 375-24ms? Assuming your calculation of 24ms is correct, I don't see why it would STOP every 1600. I would expect it to burst once every 1600.

JaBa:
i is incremented each time through the Loop. If it is less than 1600, it waits 375ms, if it is exactly 1600, it does the LCD which takes 24ms... Shouldn't you then wait 375-24ms? Assuming your calculation of 24ms is correct, I don't see why it would STOP every 1600. I would expect it to burst once every 1600.

375 is micro second and 25 is milli seconds. Every step is 750 micro second interval. So at 1600 step when the motor complete one rotation the LCD displays which takes 25ms. So i just let that 25 ms as the off time for the PWM. Since i am not able to manipulate that.

Don’t use delay() or delayMicroseconds() in a program like that. Use millis() or micros() to manage timing. Have a look at the second example in this Simple Stepper Code

If you use non-blocking timing then variations caused by other code should be handled automatically.

When people speak of PWM they usually mean the output produced by analogWrite() which is used to control a DC motor, not a stepper motor.

And please use the code button </>so your code looks like thisand is easy to copy to a text editor

…R

@Robin2

Thanks for your reply Robin. Anyway I still have a question, how does using millis() will change the timing in my code. I still have to use Delay to produce delay in the circuit.

tvmkamal:
Anyway I still have a question, how does using millis() will change the timing in my code. I still have to use Delay to produce delay in the circuit.

The purpose of using millis() is to get the same timing without using the delay() function. When you use delay() the Arduino just sits twiddling its thumbs instead of doing something useful. For example, while waiting for the kettle to boil you could stand around looking at it or you could empty the dishwasher.

If that does not help please explain in more detail what you don't understand.

...R

None of this addresses the problem of the TFT code blocking for 24ms.

The only solution I can see is to drive the step pulses by interrupt, so it can progress
during the compute-bound TFT stuff (assuming that it doesn't inhibit interrupts).

MarkT:
None of this addresses the problem of the TFT code blocking for 24ms.

The OP does not have to do the TFT code as a single block. It could be organized to do a little at a time between steps.

...R

Calls like tft.fillScreen (BLACK) ; are necessarily going to take a long time as one or two bytes
have to be passed over SPI for every pixel on the screen - that's how TFT drivers work.

MarkT:
Calls like tft.fillScreen (BLACK) ; are necessarily going to take a long time as one or two bytes
have to be passed over SPI for every pixel on the screen - that's how TFT drivers work.

I have never used a TFT. I wonder is it possible to BLACK one line at a time?

...R

Perfectly possible...

Hi Mark,

Thanks for your response. Could you please give me some points regarding 'BLACK one line at a time' ?
By doing so will i be able to overcome my problem? Or including Interrupt will be a good option?

Haven't used the Adafruit graphics library - there ought to be a line or rectangle fill operation I hope.
paint the screen in small steps checking for steps inbetween, then you don't block for long periods of
time.