Dual MC33926 Arduino Shield and 1209 Stepper Motor

Hi there,

Is it possible to use an MC33926 Arduino Shield to drive a Pololu 1209 2.7 V 1000ma Bipolar stepper motor? https://www.pololu.com/catalog/product/1209

If it’s possible, can someone help me figure out how to drive the stepper motor?

My motor is connected so that the Black and Green wires are connected to M1A and M1B and Red and Blue are connected to M2A and M2B, based on this diagram

Supplying an offboard power supply of 9 v, I believe I need to pulse M1 and M2 intermittently to advance the motor. I’m using the library available at https://github.com/pololu/dual-mc33926-motor-shield
My sketch basically looks like this:

#include "DualMC33926MotorShield.h"

DualMC33926MotorShield md;

void setup()
{
  md.init();
}

void loop()
{
  md.setM1Speed(200);
  md.setM2Speed(0);
  delay(500);
  md.setM1Speed(0);
  md.setM2Speed(200);
  delay(500);
}

My choice of delay(500) is arbitrary. The most I’ve been able to achieve is making the motor step a tiny bit forward and reverse. Any suggestions?

You need to pulse them in a sequence of positive and negative.

  1. A positive, B 0
  2. A 0, B positive
  3. A negative, B 0
  4. A 0, B negative
  5. repeat from 1

You can also do half-steps by adding the diagonals as intermediate steps, where A and P are both positive (1.5), A is negative and B positive (2.5), etc.

Using speeds other than “full forward” and “full reverse” is generally not needed or a good idea. You can, with very much twiddling, perhaps implement microstepping by using intermediate speed values, but I wouldn’t recommend trying it until you’re very familiar with both your motor, your controller, and the timers and libraries of your microcontroller.

Rugged circuits has an arduino shield that also uses drivers that can be drive 2 dc motors, or 1 bipolar stepper motor. They have example code that uses in turn some libraries designed for Adafruit’s arduino shield that uses the same situation.

I would start by examining what they do in their rugged circuits motor shield, and I believe you might find an answer there. It might be easier to just pick up an a4988, though. Or DRV8825.

Hello,

Below is a sample code to run a stepper motor with the MC33926 Motor Driver Shield (pololu.com/catalog/product/2503). Additionally this code shows how you can adjust the size of the step between full step, half step and quarter step. See the comments in the code for more detail.

#include "DualMC33926MotorShield.h"

DualMC33926MotorShield md;


#define QUARTER_STEP	1
#define HALF_STEP		2
#define FULL_STEP		4

unsigned char stepMode = FULL_STEP;


// Advances the stepper motor by one step either clockwise or counterclockwise
// with the direction specified by the argument dir (0 or 1).  The size of the
// step depends on stepMode and can either be a full step, a half step, or a
// quarter step.  Full stepping is produced by repeating a four-state cycle
// in which both coils are always energized to carry the same magnitude of current
// but the direction of the current is sequentially switched.  Running through the
// four-state cycle in the reverse order reverses the direction of rotation.  The
// general equation for coil current should be as follows:
// coil 1 current = I * sin(a)
// coil 2 current = I * cos(a)
// When full stepping, the four states are: 
// forwards: a = 0, 90, 180, 270 degrees
// reverse:  a = 0, 270, 180, 90 degrees
// half stepping comes from: a = 0, 45, 90, 135, 180, 225, 270, 315 degrees
// quarter stepping comes from a = the 16 multiples of 22.5 from 22.5 to 360 deg
void one_step(unsigned char dir)
{
	// this static variable lets us remember what step we're on so we
	// can change to the appropriate next state in the sequence
	static unsigned char step = 0;

	// compute the next step based on the direction argument dir
	// and the step mode.  Full stepping skips half and quarter steps,
	// and half stepping skips quarter steps.  Quarter stepping cycles
	// through all 16 steps.
	if (dir == 1)
		step += stepMode;
	else
		step -= stepMode;

	switch (step & 15)
	{
		case 0:	// full step (both coils energized at 71%)
			md.setSpeeds(180, 180);
			break;
		case 1:	// quarter step (coil 1 at 38% and coil 2 at 92%)
			md.setSpeeds(98, 236);
			break;
		case 2: // half step (coil 1 at 0% and coil 2 at 100%)
			md.setSpeeds(0, 255);
			break;
		case 3: // quarter step
			md.setSpeeds(-98, 236);
			break;
		case 4: // full step
			md.setSpeeds(-180, 180);
			break;
		case 5: // quarter step
			md.setSpeeds(-236, 98);
			break;
		case 6: // half step
			md.setSpeeds(-255, 0);
			break;
		case 7: // quarter step
			md.setSpeeds(-236, -98);
			break;
		case 8: // full step
			md.setSpeeds(-180, -180);
			break;
		case 9: // quarter step
			md.setSpeeds(-98, -236);
			break;
		case 10: // half step
			md.setSpeeds(0, -255);
			break;
		case 11: // quarter step
			md.setSpeeds(98, -236);
			break;
		case 12: // full step
			md.setSpeeds(180, -180);
			break;
		case 13: // quarter step
			md.setSpeeds(236, -98);
			break;
		case 14: // half step
			md.setSpeeds(255, 0);
			break;
		case 15: // quarter step
			md.setSpeeds(236, 98);
			break;
	}
}


// This is a blocking function that repeatedly takes a single step and then
// delays for step_delay_us microseconds.  When it finishes, the stepper motor
// coils will continued to be energized according to the final step so that
// the stepper motor maintains its position and holding torque. 
void multistep(int steps, unsigned int step_delay_us)
{
	unsigned char dir = 1;
	if (steps < 0)
	{
		dir = 0;
		steps = -steps;
	}

	while (steps--)
	{
		one_step(dir);
		delayMicroseconds(step_delay_us);
	}
}

void setup()
{
	md.init();
}


void loop()
{
	if (stepMode == FULL_STEP)
		stepMode = HALF_STEP;
	else
		stepMode = FULL_STEP;
	multistep(400, 5000);
	delayMicroseconds(500);
	unsigned char i;
	for (i = 0; i < 4; i++)
	{
		multistep(-100, 2000);
		delayMicroseconds(100);
	}
}

This code was adapted from the stepper-motor1 example for the Orangutan, which can be found at this link: github.com/pololu/libpololu-avr … or1/test.c

- Takuya Jeremy

1 Like

Thank you all for the help - this is exactly what I was looking for! I’ll try to get this working tomorrow - I forgot my shield at the office - and let you know if I’ve had success.

jwatte: I tried your solution first as a basic sketch. Thanks for the help: this works great for me:

#include "DualMC33926MotorShield.h"

DualMC33926MotorShield md;
const int delay_time = 50;
int forward[4][2] = {{200, 0}, {0, 200}, {-200, 0}, {0, -200}};
int reverse[4][2] = {{0, 200}, {200, 0}, {0, -200}, {-200, 0}};
void stopIfFault()
{
  if (md.getFault())
  {
    Serial.println("fault");
    while(1);
  }
}

void setup()
{
  Serial.begin(115200);
  Serial.println("Dual MC33926 Motor Shield: Stepper");
  md.init();
}

void loop()
{
  step_motor(reverse);
}
void step_motor(int dir[4][2]){
  int i = 0;
  for (i = 0; i < 4; i++){
    md.setM1Speed(dir[i][0]);
    md.setM2Speed(dir[i][1]);
    delay(delay_time);
  }
  return;
}

Takuya, thanks for taking the time to share that. I’ll give it a try this evening.

Hello.

Please note that the example code Jeremy (Takuya) posted above has one mistake and one caveat regarding usage that should be mentioned. First, it seems to be treating the maximum motor speed as 255, but the DualMC33926MotorShield library he is using has a maximum motor speed of 400, so all the motor speed values should be scaled up accordingly. This brings me to the caveat:

In its current form, there’s no provision for limiting the maximum coil voltage, which could damage stepper motors with rated voltages below the driver voltage. A better version of this program would have a constant defined at the beginning (or an extra function argument) that sets the maximum speed, and oneStep() would use appropriately scaled speeds based on this maximum.

- Ben

I took Ben’s feedback and improved the code. Please look at the comments in the code carefully. You will have to set the percentOutput value to meet the specifications of your motor.

#include "DualMC33926MotorShield.h"
DualMC33926MotorShield md;

// If you want to use the VNH5019 Dual Motor Shield instead, comment out the two lines
// above and uncomment the two lines below. 
// #include "DualVNH5019MotorShield.h"
// DualVNH5019MotorShield md;

// The constant below will scale the peak output voltage to the motor by the percentage 
// declared.  For example, if you want the peak voltage to the motor to be equal to VIN,
// set percentOutput to 100.  If you want the peak voltage to the motor to be 80% of VIN, 
// set percentOutput to 80.  You should see what voltage the stepper motor is rated for 
// and set percentOutput appropriately.  The value of percentOutput should be between 0 
// and 100. 
const byte percentOutput = 50; 

#define QUARTER_STEP   1
#define HALF_STEP      2
#define FULL_STEP      4
unsigned char stepMode = FULL_STEP;

// This function will set the voltage applied to each coil. 
inline void set_speeds(int m1speed, int m2speed)
{
	md.setSpeeds(m1speed/2*percentOutput/50, m2speed/2*percentOutput/50);
}

// Advances the stepper motor by one step either clockwise or counterclockwise
// with the direction specified by the argument dir (0 or 1).  The size of the
// step depends on stepMode and can either be a full step, a half step, or a
// quarter step.  Full stepping is produced by repeating a four-state cycle
// in which both coils are always energized to carry the same magnitude of current
// but the direction of the current is sequentially switched.  Running through the
// four-state cycle in the reverse order reverses the direction of rotation.  The
// general equation for coil current should be as follows:
// coil 1 current = I * sin(a)
// coil 2 current = I * cos(a)
// When full stepping, the four states are: 
// forwards: a = 0, 90, 180, 270 degrees
// reverse:  a = 0, 270, 180, 90 degrees
// half stepping comes from: a = 0, 45, 90, 135, 180, 225, 270, 315 degrees
// quarter stepping comes from a = the 16 multiples of 22.5 from 22.5 to 360 deg
void one_step(unsigned char dir)
{
   // this static variable lets us remember what step we're on so we
   // can change to the appropriate next state in the sequence
   static unsigned char step = 0;

   // compute the next step based on the direction argument dir
   // and the step mode.  Full stepping skips half and quarter steps,
   // and half stepping skips quarter steps.  Quarter stepping cycles
   // through all 16 steps.
   if (dir == 1)
      step += stepMode;
   else
      step -= stepMode;

   switch (step & 15)
   {
      case 0:   // full step (both coils energized at 71%)
         set_speeds(283, 283);
         break;
      case 1:   // quarter step (coil 1 at 38% and coil 2 at 93%)
         set_speeds(153, 370);
         break;
      case 2: // half step (coil 1 at 0% and coil 2 at 100%)
         set_speeds(0, 400);
         break;
      case 3: // quarter step
         set_speeds(-153, 370);
         break;
      case 4: // full step
         set_speeds(-283, 283);
         break;
      case 5: // quarter step
         set_speeds(-370, 153);
         break;
      case 6: // half step
         set_speeds(-400, 0);
         break;
      case 7: // quarter step
         set_speeds(-370, -153);
         break;
      case 8: // full step
         set_speeds(-283, -283);
         break;
      case 9: // quarter step
         set_speeds(-153, -370);
         break;
      case 10: // half step
         set_speeds(0, -400);
         break;
      case 11: // quarter step
         set_speeds(153, -370);
         break;
      case 12: // full step
         set_speeds(283, -283);
         break;
      case 13: // quarter step
         set_speeds(370, -153);
         break;
      case 14: // half step
         set_speeds(400, 0);
         break;
      case 15: // quarter step
         set_speeds(370, 153);
         break;
   }
}

// This is a blocking function that repeatedly takes a single step and then
// delays for step_delay_us microseconds.  When it finishes, the stepper motor
// coils will continued to be energized according to the final step so that
// the stepper motor maintains its position and holding torque.
void multi_step(int steps, unsigned int step_delay_us)
{
   unsigned char dir = 1;
   if (steps < 0)
   {
      dir = 0;
      steps = -steps;
   }

   while (steps--)
   {
      one_step(dir);
      delayMicroseconds(step_delay_us);
   }
}

void setup()
{
   md.init();
}

void loop()
{
   if (stepMode == FULL_STEP)
      stepMode = QUARTER_STEP;
   else
      stepMode = FULL_STEP;
   multi_step(400, 5000);
   delayMicroseconds(500);
   for (byte i = 0; i < 4; i++)
   {
      multi_step(-100, 2000);
      delayMicroseconds(100);
   }
}

-Jeremy

1 Like

I’ve been tinkering with this code and the mc33926 shield for a few days now. I can run this stepper motor with no problem when it is connected half-winding, but I want to use all 4 coils by connecting them in series configuration. Like this:
When I try to run the motor I get the same result after everything I do. The motion has no strength and is not consistently going in one direction. I was wondering if you think this might be because the set_speeds values are conflicting and cancelling out one another in this wire configuration. How do you figure out these values for this setup?

Hello.

You should be able to configure your 8-wire stepper motor to a 4-wire configuration like in the picture. Do you have the correct wires tied together? If the coils are not connected correctly, it might lead to unexpected behavior. Could you tell us more about your stepper motor? Could you provide a link to its datasheet? What are you using to power the motor and driver? Could you post pictures of your setup?

- Jeremy

Your comment that it should work makes me realize that my problem is the stepper motor. One of the sets of coils isn’t insulated. Essentially connecting inside the motor. What do you think about that?
I can’t take pictures at this time. I have a motor I believe is specially made for a printer so no data sheet can be found.I wanted to repurpose it for my project instead of buying a new one. (sanyo denki 103h7125-0641) Power supply is Mean Well SP 240-24

I am not sure I understand what you mean by the coils are not insulated, and that they are connected inside the motor. If you get a chance to post pictures, hopefully they will clarify the situation.

- Jeremy

I bought a new motor and that fixed my old issue. Now my project is almost finished. The thing holding me back is the step_delay_us setting. How do you come up with the values for this. I tried a few calculations and I tried to make a chart of them. I can’t see the pattern.

Hello.

I am not entirely sure I understand what it is you are asking; can you clarify? As you can see inside Jeremy’s code, step_delay_us is a parameter of multi_step() that determines the step rate used during the multi-step. The program sets step_delay_us to 5000 and 2000 inside loop().

-Jon

If I want to take 4 seconds to make one turn that’s 50 delays per rotation. So I set the value to 80000 because that’s 4000000/50. That worked, but I wanted it to go even slower. So I tried 6000000/50 to get a delay of 1200000 but the speed increased. After that I added another delay to to get the right speed. Why did the speed increase?

Incredibly, my new 425 oz motor wasn’t strong enough. I plan to step up the power with this motor. automationtechnologiesinc.co … 30-4BM.pdf It seems to be right on the cusp of the shields capability. Do you recommend anything?

That behavior makes it seem like an integer overflow, where the value your code tries to store into the unsigned int is larger than the maximum value it can store. To overcome this, you might consider making delays in larger increments of time. For example, you could change

delayMicroseconds(step_delay_us);

to

delay(step_delay_us);

which would make the delay 1000 times greater - in milliseconds instead of microseconds.

And you could probably rename step_delay_us to step_delay_ms to be more accurate.

As for the stepper motor you linked to, it looks like it draws 3A per coil, which is pushing the limits of what the MC33926 can handle continuously.

-Jon

I tried to run the motor with the mc33926 shield. It worked during testing. When I went to put it all together I made some mistakes. I was soldering with the arduino plugged in and I ruined it. I also cut a wire and it sparked. I got a new arduino and I want to get a new mc33926.

My questions are will the shield handle 3 amps continuously like it says?
Will heatsinks and a fan allow it to handle the current better?
Does current increase if the torque is being resisted?

On another note, I want to thank Pololu for this forum. It has answered other questions I’ve had and I’m happy to be a part of it.

In our tests with the driver at ambient temperatures with no additional cooling it was able to handle 3A continuously. However, the exact amount of current you will be able to pull might depend on your setup. Adding a heat sink and providing external cooling can help the motor driver handle more current safely.

Yes, a brushed DC motor will draw more current when a larger load is place on it like that.

-Jon

Hi,

is it possible to use the Dual MC33926 Motor Driver Carrier with an arduino to drive a stepper motor? If so, what changes in the code and how to wire it?

Thanks a lot