Stepper motor cause problems with counting pulses

Hello!

I am counting pulses from my two signal generators with my Arduino, and I am trying to convert these pulses into steps for my stepper motor. The pulse counter works just fine in itself, but when i add the stepper.setSpeed and stepper.step-commandos to my project it makes the pulse counter not work properly - because it is counting the wrong amount of pulses.

  1. Could the problems be caused by delays in the Stepper.h-library?
  2. Is it possible to only use the stepper.step-commando and not the stepper.setSpeed? Because i want the pulses from my signal processor to determine the speed on my stepper motor.
  3. Do you guys if it exists a stepper-library without any delay, so it doesnt ruin my pulse counter?

I would appreciate if you guys could help me out! :slight_smile:

I could share the arduino code if it is necessary, but it is incredibly long and complex and I dont know if you guys have the time to understand my programming. Therefore I would prefer if you guys could try and answer my questions instead :slight_smile:

The attached picture shows the layout for the pulse counter to LCD, but I havent included the stepper-motor

My code, if its interesting for anyone :slight_smile:


volatile unsigned long count = 0; // defines count
volatile unsigned long rotasjon = 0; // defines rotation

volatile uint8_t pressed = 0; // defines what pressed
volatile uint8_t flag = 0; // defines flag

#include <Stepper.h> // includes library for stepper-motor
#define STEPS 200 // amount of steps on my stepper-motor
Stepper stepper(STEPS, 8, 9, 11, 12); // defins the wiring


#include <LiquidCrystal.h> // includes library for LCD monitor

LiquidCrystal lcd(1, 10, 4, 5, 6, 7); // defines rs, enable, d4, d5, d6 and d7 

byte a[8] = { // animated drawing of radar top left corner
  B00000,
  B00011,
  B00100,
  B01000,
  B01000,
  B10000,
  B10000,
  B10000
};

byte b[8] = { // top middle
  B11111,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000
};

byte c[8] = { // top right corner
  B00000,
  B11000,
  B00100,
  B00010,
  B00010,
  B00001,
  B00001,
  B00001
};

byte d[8] = { // bottom left corner
  B10000,
  B10000,
  B01000,
  B01000,
  B00100,
  B00011,
  B00000,
  B00000
};

byte e[8] = { // bottom middle
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B11111,
  B00000
};

byte f[8] = { // bottom right corner
  B00001,
  B00001,
  B00010,
  B00010,
  B00100,
  B11000,
  B00000,
  B00000
};

byte g[8] = { // radar sweep north
  B11111,
  B00000,
  B00100,
  B00100,
  B00100,
  B00100,
  B00100,
  B00100
};

byte h[8] = { // radar sweep south
  B00100,
  B00100,
  B00100,
  B00100,
  B00100,
  B00000,
  B11111,
  B00000
};

  byte i[8] = { // radar sweep east number 3
  B00000,
  B11000,
  B00100,
  B00010,
  B00010,
  B00001,
  B00001,
  B11101
};

byte j[8] = { // radar sweep east number 2
  B11111,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00111
};

  byte k[8] = { // radar sweep left 1
  B00000,
  B00011,
  B00100,
  B01000,
  B01000,
  B10000,
  B10000,
  B10111
};

byte l[8] = { // radar sweep left 2
  B11111,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B11100
};
  byte m[8] = { // north east 2
  B11111,
  B00000,
  B00000,
  B00000,
  B00000,
  B00001,
  B00010,
  B00100
};

byte n[8] = { // north east 3
  B00000,
  B11000,
  B00100,
  B00010,
  B10010,
  B00001,
  B00001,
  B00001
};

  byte o[8] = { // south east 5
  B00010,
  B00001,
  B00000,
  B00000,
  B00000,
  B00000,
  B11111,
  B00000
};

byte p[8] = { // south east 6
  B00001,
  B00001,
  B10010,
  B00010,
  B00100,
  B11000,
  B00000,
  B00000
};

  byte q[8] = { // south west 5
  B01000,
  B10000,
  B00000,
  B00000,
  B00000,
  B00000,
  B11111,
  B00000
};

byte r[8] = { // south west 4
  B10000,
  B10000,
  B01001,
  B01000,
  B00100,
  B00011,
  B00000,
  B00000
};

  byte s[8] = { // north west/1
  B00000,
  B00011,
  B00100,
  B01000,
  B01001,
  B10000,
  B10000,
  B10000
};

byte t[8] = { // north west/2
  B11111,
  B00000,
  B00000,
  B00000,
  B00000,
  B10000,
  B01000,
  B00100
};


void setup() 
{
  pinMode(2, INPUT); // Reset pulse
  pinMode(3, INPUT); // Pulses in (ACP)
   attachInterrupt(digitalPinToInterrupt(2), do_flag,  CHANGE); // counting reset at change 
   attachInterrupt(digitalPinToInterrupt(3), count_inc, FALLING); // counting pulses at falling

 lcd.begin(16,2); // defines size on LCD and starts it up
  lcd.createChar(1, a); // makes my drawings, the defines bytes earlier in the project defines which bytes are gonna light up
  lcd.createChar(2, b);
  lcd.createChar(3, c);
  lcd.createChar(4, d);
  lcd.createChar(5, e);
  lcd.createChar(6, f);
    lcd.setCursor(13, 0); // placement for the custom characters
      lcd.write(1); // top left
    lcd.setCursor(14, 0); //
      lcd.write(2); // top middle
    lcd.setCursor(15, 0);
      lcd.write(3); // top right
    lcd.setCursor(13, 1);
      lcd.write(4); // bottom left
    lcd.setCursor(14, 1);
      lcd.write(5); // bottom middle
    lcd.setCursor(15, 1);
      lcd.write(6); // bottom right

  lcd.setCursor(9, 1); // decides where text is displayed on LED
    lcd.print("R:"); // defines text, R is for rotatin
  lcd.setCursor(12, 0);
  lcd.print((char)223);
 
  lcd.setCursor(11, 1);
    lcd.print(rotasjon++); // counts rotations, adds one for each rotation

  lcd.setCursor(0, 1);
    lcd.print("TOT:");

  lcd.setCursor(0, 0); // defines where LCD is printing
    lcd.print("ACP:"); // prints text before the pulses (NB! big difference between write and print)


}

void loop() 
{   
  char msg[4];
    sprintf(msg, "%4d", count);
      lcd.setCursor (4, 0); lcd.print(msg); // counts ACP with four digits
 
  if (count*0.087890625 > 99) 
  {
    lcd.setCursor (9, 0); // position in grades
    lcd.print(count*0.087890625, 0); // from pulses to grades
  }
  else
  {
    lcd.setCursor (10, 0); // position in grades
    lcd.print(count*0.087890625, 0); // from acp to grades
  }

  if (count*0.087890625 < 99) 
  {
    lcd.setCursor (9, 0); // pos in grades
    lcd.print(" "); // from acp to grades
  }
 

  if (count < 3) // if count is less than then do:
  {

    lcd.setCursor(9, 1); // 
      lcd.print("R:");
    lcd.setCursor(11, 1); // 
      lcd.print(rotasjon++);
  }
  if (count<512) // north
  {
    lcd.createChar(8, g);

    lcd.setCursor(13, 0);
      lcd.write(1);
    lcd.setCursor(14, 0);
      lcd.write(8);
}
  if ((count>512) && (count<1024)) // north east
  {
    lcd.createChar(7, m);
    lcd.createChar(8, n);

    lcd.setCursor(14, 0);
      lcd.write(7);
    lcd.setCursor(15, 0);
      lcd.write(8);
  }
  if ((count>1024) && (count<1536)) // east
  {
    lcd.createChar(7, j);
    lcd.createChar(8, i);
  
    lcd.setCursor(14, 0); 
      lcd.write(7);
    lcd.setCursor(15, 0);
      lcd.write(8);
  }
  if ((count>1536) && (count<2048)) // south east
  {
    lcd.createChar(7, p);
    lcd.createChar(8, o);

    lcd.setCursor(14, 0); // fixes last one
      lcd.write(2);
    lcd.setCursor(15, 0);
      lcd.write(3);

    lcd.setCursor(14, 1); // new one
      lcd.write(8);
    lcd.setCursor(15, 1);
      lcd.write(7);
  }
  if ((count>2048) && (count<2560)) // south
  {
    lcd.createChar(8, h);

    lcd.setCursor(14, 1); // fixes
      lcd.write(5);
    lcd.setCursor(15, 1);
      lcd.write(6);
 
    lcd.setCursor(14, 1); // new
      lcd.write(8);
  }
  if ((count>2560) && (count<3072)) // south west
  {
    lcd.createChar(7, q);
    lcd.createChar(8, r);

    lcd.setCursor(14, 1); // fixes
      lcd.write(5);

    lcd.setCursor(13, 1); // new
      lcd.write(8);
    lcd.setCursor(14, 1);
      lcd.write(7);
  }
  if ((count>3072) && (count<3584)) // west
  {
    lcd.createChar(7, k);
    lcd.createChar(8, l);

    lcd.setCursor(13, 1); // fixes
      lcd.write(4);
    lcd.setCursor(14, 1);
      lcd.write(5);

    lcd.setCursor(13, 0); 
      lcd.write(7);
    lcd.setCursor(14, 0);
      lcd.write(8);
  }
  if (count>3584) // north west
  {
    lcd.createChar(7, s);
    lcd.createChar(8, t);
 
    lcd.setCursor(13, 0); // new
      lcd.write(7);
    lcd.setCursor(14, 0);
      lcd.write(8);
  }  
 
  if (count > 4090)
  {
    lcd.setCursor(4, 1);
      lcd.print(count);
  }
  if ((count >=3000) && (count<= 3010))// 
  {
    lcd.setCursor(4, 1);
      lcd.print("    ");
  }
//
// if(count > 2048)
  stepper.setSpeed(10); // trying to turn motor
  stepper.step(-1);
 //   lcd.setCursor(10, 0); 
 //   lcd.print(stepCount);
 // stepCount++;
//}
 



// }
}

void do_flag() 
{
  if (flag == 0) 
  {
    flag = 1;
    pressed = 1;

  }
  else
  {
    count = 0;
    flag = 0;


  }
}

void count_inc() 
{
  if (flag == 0)
  {
    count++;
  } 
}

Can you bypass the arduino and feed the pulses directly into the stepper driver's pulse input?

Make msg[5] to allow for the zero string terminator.

You miss 512, 1024, 1536 etc. in your decisions.

Have you already tried the AccelStepper library?

I'm confused by the stepper part of your code. Your code seems to only move the stepper one step every loop. What size stepper are you using? A name 17 is going to have 200 steps per revolution but a tiny 28BYJ-48 is going to have 2053 steps per revolution. You are never going to see 1 step.
Also, what type of driver are you using for your stepper? You're not trying to drive the stepper directly off the arduino are you? You need a full H-bridge driver to drive something like a stepper.

Also, you want the signal to determine the speed of the stepper? or it's position? Because you are setting the speed to a constant every time you cycle through the loop. And that speed is VERY slow. A name 17 stepper will cruise at around 50 RPM and a BYJ can go up to 20 easily.

I am using an TB6612 driver and stepper type 42SHD0217 with 200 seps.

Also I tried to add this code, I wanted to move the stepper one step for every 20th pulse. But somehow it makes the pulse counter count wrong.

Edit #1: I made a counter which Is supposed to count the pulses, and when it reaches 20 it moves the stepper one step and resets the counter. I get about 350pulses per second from my signal generator.

Edit #2: My goal is to use the siginal generator pulses to decide the rotation of the stepper motor. So if I change frequency I can see the RPM of my motor change.

 
 if (digitalPinToInterrupt(3), FALLING)
  {    
    acpStepper++;
  } 
  
  if (acpStepper == 21)
  {
    stepper.step(-1);
    acpStepper = 0;
  } 


That could maybe work. But my pulse generator creates about 350 pulses each second, and I think that will be too quick for my stepper. I wanted the stepper to move one step for each 20th or 50th pulse.

I am sorry but I dont understand what you mean by zero string terminator.

I dont think I am missing any pulses, because the pulse counter only goes up to about 4000 before it is reset, thats why i only need 4 digits on my LCD-display.

I have not tried the AccelStepper library. Do you think that would fit me better?

Each C string is terminated by an extra NUL character for which must be room in the char array.

Oh okay. I am on deep water right now, and I will be honest and say I dont understand everything in my project. I have just mixed a bunch of different programs online and troubleshooted into it finally worked.
I tried changing to msg[5] but I dont see any difference. The numbers move so fast anyways, so its not critical if some numbers doesnt show up on the LCD-display.

When i have // (slashes) before " stepper.step(-1); " my pulse counter works as it is supposed to, but as soon as i remove the slashes it makes my pulse counter misscount by 2-3 pulses. Does anyone know why this happens?

It is a coincidence what happens when your char array is too short. So you may not see a change directly - maybe you have misbehaviour when you change something in your sketch in a completely different place. That's why this error (too short an array) is very dangerous. Anything can happen - you overwrite an arbitrary value in ram - what the compiler positioned directly after your array - and you don't know what this is.

Stepper.step(-1) doesn't mean, that a step is executed immediately. There maybe a delay regarding to the set speed.
If you want the stepper to step every 20th pulse, you must not use a stepper library, but create the pulse directly by yourself. Stepper libraries always create pulses according to the set speed, and not necessarily immediately.

The driver you use doesn't fit to your motor. This stepper is constructed to be used with a current-controlling driver, not a simple H-bridge as the TB6612.

1 Like

Thanks for your answer.

  1. So you recommend using msg[5]?
  2. Yeah, thats what i thought. Is it possible to remove the delay from the library or is it easier to create everything by myself?
  3. When i connect the VM+ pin on the driver to a 9V battery the stepper works. Will this harm the motor?

You MUST do that.

I doesn't make sense to remove the delay from the library. The library is designed to step the motor with the set speed. Anything alse doesn't make sense.
In your case it should be more easy to use a step/dir driver that fits to your motor and create the step pulses by yourself.

A 9V battery isn't a useful power source for your motor. It cannot provide the current the motor needs. I think it will limit the current by itself and so not harm your motor, but maybe itself. And the motor will not have much torque, and the battery will not last long.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.