Controlling 81 stepper motors with an Arduino Mega

Thread Starter

stef757

Joined Apr 28, 2011
9
Hello all, I could use some help from those more experienced with the design of μC code. I am working on a project in which I want to control 91 individual stepper motors using the Arduino Mega. Before you just write me off as crazy, I'll give you a description of the system.

The system is 81 linear actuators in a 9x9 array. The linear actuators are actuated using the stepper motors on a gear box assembly. You can think of it as a digital "Pin Art" toy. We are using a Microsoft Kinect to collect 3D data which will be downsampled to 9x9 and scaled according to our depth transfer function. Each linear actuator has a range of 8 cm with a step range of 127 steps (~0.62 mm/step). The 3D data is going to be scaled to this 7-bit value. The idea here is the "display" made of the linear actuators is going to be reproducing a 3D relief of whatever is in the Kinects defined imaging region. The 91 individual points are to be processed on a computer and transmitted via USB to the Arduino Mega, where the motion planning will be going on. The sample rate is going to be 10Hz. I've attached a block diagram of the system.


The stepper motors are 20 step/rev bipolars rated for 5v. Each will be pulling about 300mA when being operated at 4V. They're small chinese motors, 15mm diameter. They're going to be operated on full steps cycles, (ie no half steps).

9 identical PCBs are going to be fabricated, each containing 9 stepper motor drivers (PN MPC17C724EP from Mouser: http://www.mouser.com/ProductDetail/Freescale-Semiconductor/MPC17C724EP/?qs=r8OyiFxb6RdTneKUVVqNtTwvmFri%252bkC%252bgfRTjo7CasU%3d).

I'm using shift registers to control the stepper motor drivers, 74HC595s. 5 pins to control each driver (4 for the coils, 1 for power save mode), meaning 6 shift registers will be used on each PCB. Since I want a max step rate of 127 steps/second and want to have a step rate frequency resolution of about +/- 2 steps/sec, I figured out that the shift registers need to be refreshed at about 14kHz.

I'm hoping to use the software serial output of the Mega to have 9 parallel outputs, one for each of the control boards with the 9 stepper drivers and 6 shift registers. The shift registers use a 3 pin interface: CLK, DATA, and EN. I was figuring all board will use a common clk and enable and have unique data inputs. I need to write the 45 bits (5 bits/motor * 9 motors) to the shift register chains of each PCB then shift it to the parallel outputs of the shift registers in 14kHz cycles.

I am still working out the actual motion planning calculations and am unsure what my limits are going to be here with the microcontroller. I will be processing 81 7-bit values 10 times a second to generate an output step frequency for the stepper motors. I think I should be able to get away with performing some simple difference calculations between the current position value and the next position value. I am thinking I will buffer 2 or 3 samples to be taken into account with the motion planning for some sort of a 'look ahead' feature. Might be useful to make smoother acceleration and deceleration plans. I'm not trying to use serious motion planning algorithms because theyre not required, and it's OK if the acceleration and deceleration movements are more approximate than exact.



I think this covers the general plan I have right now. I have some experience with microcontrollers but this project is definitely more complicated than anything I have programmed before. I could really use some advice from those more experienced, even if the plan I have right now isn't likely to work, knowing that will help me get closer to something that does work. As I start to put the code together, hopefully I can get some help building it into a clean and compartmentalized code. Thanks for taking the time to give this a read!
 

Attachments

John P

Joined Oct 14, 2008
2,026
The stepper motors are 20 step/rev bipolars rated for 5v....

I'm using shift registers to control the stepper motor drivers, 74HC595s. 5 pins to control each driver (4 for the coils, 1 for power save mode), meaning 6 shift registers will be used on each PCB.
You say the motors are operated in single-step mode, so how can there be 4 coil drivers? I'd have thought each coil would be on all the time and you'd just be controlling the polarity.

If I were doing this project I would do my best to have all the shift registers in a single chain, then operate them over an SPI port. Keep the wiring and the processing simple!

Edited to say, I just went and looked at the driver component. Although it is for bipolar motors, you apparently have to drive its inputs in complementary fashion, 2 per coil where one is high and the other low. I'd be tempted to put inverters out there on the cards to avoid having to send duplicated data, though it would depend on whether you want the 00 (both ends of the coil low) or 11 (both ends hi-Z) features.
 
Last edited:

MrChips

Joined Oct 2, 2009
30,806
If I were doing this project I would make each motor controlled by its own MCU with an RS-485 interface. All controllers are connected to a master controller via a single 2-wire network.
 

kubeek

Joined Sep 20, 2005
5,795
Depends on the distance, for somehting small the shift registers are a perfectly valid option, as long as the refresh rate is small. For something large the separate uCs would be more reliable.
You don´t really need 9 uarts to make this work, you can easily do this in software, use two output ports for the data lines, in each shift you output two bytes on the two ports, then send the clock pulse to shift it. The stcp, oe and mr lines of all the shift registers can be tied together, so the control will be pretty easy. Atmegas can run on up to 20mhz, so with 14khz data rate you have aproximatle 1500 instructions per shift to spare, so you should have no problems with the microcontroller being too underpowered for the task.
 

Thread Starter

stef757

Joined Apr 28, 2011
9
Thanks for all the replies! In regards to some of your questions -

The stepper motors have 4 control pins because they have 2 coils, and to step it in one direction there are 4 sequences before it repeats:
Coil:
1a 1b 2a 2b
1 0 0 1
1 1 0 0
0 1 1 0
0 0 1 1

Yes, you could use inverters to reduce it to 2 control lines an possibly reduce the number of motor drivers I am using, but the inverters would have to be power inverters anyway and keeping one motor driver per motor was keeping it more simple and straight forward in my mind. Theres also the fact that I need to be able to turn off the motors when they are not in motion to save power.

There were some plans to put everything in a one chain, but that was changed to reduce transmitting time. Plus, I was under the impression that theres a limit to how many shift register ICs you can chain together (though I just looked at the datasheet and couldn't find a spec for that)

The first plan was to put an MCU on each board, so 9 in total. The 9 MCUs were going to receive the data from the computer in cascade, where the computer is the master and the 9 MCUs the slave. I changed over to trying to use one Arduino Mega to simplify the design because I was having a hard time figuring out how to design the microcontroller from scratch and to deal with all of the different data paths (receiving data from the PC in cascade, processing the data, outputting the data to the shift registers).

Luckily the shift registers are completely capable of working at a rate of up to 20 MHz.
Kubeek- this is pretty much how I am hoping for this to work. 2 ports for output. With the 14kHz cycles and 45 bits per pin per cycle, the shift registers would have to be written to at a minimum of 630 kHz. I'm curious how you calculate the number of instructions available?

How would one suggest I set up the timing sequences in the code? Should I be using the Time functions of arduino, and just work with the micros() function? What's going to be the best way to receive the data from the computer while all of this other stuff is going on? Since its a pretty small pack of data, only 567 bits, I suppose it would be easy to squeeze that in between the other operations every 1/10th of a second.
 

kubeek

Joined Sep 20, 2005
5,795
Frankly I am a little lost on how you got to those 14khz anyway. You have to send out 45 bits for one refresh of the shift registers state - i.e. one step of the motor, and you want to achieve 127 steps a second. That tells me that you need to transmit at at least 5715 bits per second to get there.

As for the receiving commands and other stuff, you typically use interrupt on the uart RX, stuff the received data into a buffer and when you get all the data the main loop takes care of it. To get a nice timing for the tx to shift regs you would use a timer interrupt, so on each tick you transfer one bit set to all 9 register chains and then prepare the next bit set.
 

Thread Starter

stef757

Joined Apr 28, 2011
9
Here's where I got the 14 kHz- I want a maximum step rate of 127 steps/s. But I also want to be able to output at 125 steps/s and 123 steps/s and so on. If i were to output to the shift registers at 127 write cycles/ second, the next smallest step rate I would be able to achieve would be half of that, 63.5 steps/s. It's kind of like implementing a Pulse Frequency Modulation.
 

kubeek

Joined Sep 20, 2005
5,795
I still don´t see how those numbers add up to 14khz, do you want to be able to send a step every 14000 times a second?
Anyway if you want a motor to turn slower, you can simply miss a step every once in a while, can´t you?
 

Thread Starter

stef757

Joined Apr 28, 2011
9
Just did the math again, it was actually more like 16 kHz. The math was

f*(f-Δf) = 127*(127-2) = 15,875 Hz.

Since dealing with the stepper motor linear actuator is dealing with a physical object with inertial properties, to make fast motions I will most likely have to ramp up and down the velocities with some acceleration and deceleration constant. I do want to be able to achieve some smooth movements with the stepper motors.

Think of it like PWM. If youre operating an LED at 30hz and employ 8 bit PWM, you're really altering the LED with a max frequency of 256*30= 7,680 Hz. Unlike PWM, the 'refresh rate' of the stepper motor is the step frequency, and this will be altered based on the frequency I need to step the motors. If you super impose two square waves on a timing diagram, one 100 Hz and one 99 Hz, you see that there is a difference of that 1/100th of a period. Its not that the output of a single pin will be toggling at 16 kHz, its that the rise and fall of an output will be variable. I don't know if I described my thoughts on it very well, much easier with a diagram.
 

kubeek

Joined Sep 20, 2005
5,795
I have no idea what load is the actuator moving, so I guess you would need to try what you can do with them without the step motor slipping. But as I think about it, the first step will allways need the most power, because after that the movement has some inertia and the force needed for the next step is allways slower. So if the motor is powerful enough to do 127 steps a second, it should be as well be able to do 126 steps a second with one pause, shouldn´t it?
Edit: the same should apply to stopping, because you stop by staying on a step anyway.

So let´s say you clock the output at 15857hz, with the chip running at 20MHz. This gives you have 1261 clock cycles per bit, and you need between 1 and 4 clock cycles per instruction. Not very much if you think you need to prepare 81 bits and set them to the ports.

Anyway since this is software, i suggest you get the hardware stuff together and then start from simple control proportional control all the way up to speed ramping and everything else you expect.
 

John P

Joined Oct 14, 2008
2,026
I have to agree with Kubeek, the processing time per bit is too much to figure out 81 outputs at this frequency, at least with a small processor. With one processor per board, i.e. running 9 motors rather than 81, it seems more feasible.

Your sequence chart:
1a 1b 2a 2b
1 0 0 1
1 1 0 0
0 1 1 0
0 0 1 1

demonstrates that 1a and 2a, and 1b and 2b, are complements and don't carry any extra information. With only 4 unique states, you could obviously send the data as 2 bits. You can decide not to do it that way, but in not using inverters, you will need more shift registers (and time to drive them).
 

Thread Starter

stef757

Joined Apr 28, 2011
9
Since the input data to the microcontroller is only being received at 10 Hz, I was hoping I'd be able to split the operations up into much process that are small enough to complete between the output operations. I think once I have a motion plan figured out, the output frequency would only be changing every 1/10th of a second. This is neglecting the acceleration and deceleration stuff going on. All of the operations that will be happening at the ~16 kHz will for the most part be defined only 10 times a second, so most of the operations being performed by the microcontroller should be output operations. Could you see it being feasible this way?
 

John P

Joined Oct 14, 2008
2,026
I think once I have a motion plan figured out, the output frequency would only be changing every 1/10th of a second.
I'm imagining that too, but what I'm also thinking is that you'd have 81 counters, each decrementing once per 1/16000 sec cycle and when they hit zero, a step is generated and they're reloaded from a register which can be reloaded at every 1/10 sec communication cycle (or maybe each register gets reloaded every cycle). There also has to be a provision for a motor not moving at all, let's say when the register is loaded with zero. So you have to do all these decrement and test operations for each of your 81 counters at every cycle, with 62.5usec to do it in. It just seems like too much to do in too little time. Or is there a more efficient way to decide when to step the motors?
 
Last edited:

ytinguely

Joined Oct 27, 2013
1
hi everybody, new member first post here.

I'm doing a project that has similar technical specification and was wondering how yours went, did you manage to do it and what kind of solution you found.

would be nice to also see the project with the kinect in action !

thanks.
 
Top