Introduction: Attiny85 As a Step/Dir Stepper Motor Controller

Picture of Attiny85 As a Step/Dir Stepper Motor Controller

Somewhere in Greece, someone did something never done before...


Seen those things before?

Thing: 1

Thing: 2

Thing: 3

Oh, you have! You bought one of them you say? Oh... Don't worry, I did too.

They did the job, yeah. But we paid for them much. Really much. And while our whole project would cost less than 60 bucks or euros without them, they slapped as in the face, then took our money and ran ... our precious motors...

The revenge has come...

Step 1: Some Things About Steppers...

We all love steppers! They do some really nice things.

1) They ran great CNC systems, that make all kinds of goods!

2) They play music, sometimes better than humans!

Basically They do only those two things but they are enough...

We, people, often control them via computers or microcontrollers and make them do those nice things and live happily together.

Steppers differ from DC motors structurally and behaviorally. They have 4 control wires (instead of 2) and, in order to make the rotor move, you have to apply voltage to some combinations of them, and change the combinations over small (really small) time intervals (maybe every 0.01 seconds or less).

Why is that, you may ask. But it is for PRECISION! The god of productive machinery! Every time you drive the stepper wires with a correct combination the rotor moves by a certain amount of degrees... That way you can tell where the rotor is by just measuring how many such voltage combinations you have applied to the motor. Knowing the position of something without any kind of feedback is Really Something!!!

(You can read much more here. There is a decent explanation of microstepping inside. the thing that this project CAN'T do at the time of writing)

Step 2: Stating the Problem...

So, as you may have realized, steppers are a hassle to use and control. All those wires, voltages, combinations and degrees/step are simply too much for a human to control.

And when it comes to CNCing, computers find it hard too. It is difficult even for computers, to control all the above combined with the needs of a CNC device: steady velocity, measured acceleration, simultaneous motion and taking a note of every rotor at any given time.

But when we face problems with multitasking we have the most elegant solution (when it comes to engineering):

Split the tasks to more than one worker. And that happened. The computer got rid of anything that has to do with voltages and combinations of wires. A simple interface was given to the computer so it could communicate with the motor. An interface that only contains 2 signals. A Step signal that every time it goes High (edge triggering) the motor has to move 1 "step" and a Direction signal that decides at which direction would be the step (ex: High for CW, Low for CCW).

So this is the Step/Dir interface.

Now a second device was needed to translate the Step/Dir signals to actual 4-wire signals, move the motor and generally do the hard work. This device is the Stepper Controller. And as of today, only one type of this device exists commercially: the hardware one. It uses H-bridges along with some kind of hardware logic, and other tricks ending up to quite complicated device. So it isn't that cheap too... They can reach even 60 euros or more for multiple motors.

So, the first reaction when I got an idea about how to program Attinies was "Why hasn't anyone made a software controller, by just coding the combinations in an Attiny85" (There have been some success with Attiny2313 by another Instructable and a sole attempt with Attiny85 that isn't very satisfying)

Step 3: The Attiny85 Problem

Picture of The Attiny85 Problem

Attiny85 is a microcontroller. It contains a processor, some RAM, some free space, to save and load things, and offers some of its processor's register bits as IO pins.

Here lies the problem. Attiny85 has 8 pins at its DIP package, 2 of them being power supply. And you may assume that the rest are pure IO. That's wrong. Well, almost, wrong... The 5 of the remaining pins are IO and there is that 1 pin that is used for RESET (if you bring it Low the microcontroller will restart). To make things worse, RESET pin is connected to some register, so it has the potential to BE an IO pin. There is also a fuse inside the microcontroller that decides if this pin is used for RESET or IO. BUT if you change the fuse (the famous RSTDSBL) to use the pin as IO, the microcontroller can't be reset again and, on top of it, it can't be reprogrammed.

Now, back to the stepper controller device. It needs 2 pins, to read the incoming Step and Dir signals, and 4 to connect the stepper motor wires (or the base of some transistors to amplify the power delivered to the motor) and do the actual voltage combinations. So a controller needs (*at least*) 6 pins.

You see it, don't you? The way god created things has made our little Attiny85 to be incapable of being used as a stepper controller properly. Until Now...

Step 4: The Circuit

Picture of The Circuit

This is the circuit.

We are using the Attiny at standard, inside-clock frequency, without external crystal. Using pins 6, 7, 2, 3 for the Stepper motor wires. Each side of the chip is used for a coil. A stepper motor has 2 coils inside it, both ends of both of them are its wires.

For Unipolar Motors

All 4 of them have to go to an array of transistors. TIP120 is a good idea, or a ULN2003 that contains 7 Darlington Transistors (like TIP120) capable of 500mA each. It is a common circuit and you can find it easily. I have added one. The a,b,c,d go to the 6,7,2,3. Use some "trial and error" for the connection order.

For Bipolar Motors

All 4 wires go to 2 H-bridges. You can find ICs containing single or dual H-bridges for 2-3 euros (that can drive up to 1-2 Amps). The 1a,1b,2a,2b are the signals to connect to the Attiny's 6,7,2,3 in this case... Again, trial and error is your friend... Be careful because h-bridges tend to heat up quickly if they get connected the wrong way...

The Step signal is read in pin 7. The microcontroller is programmed in a way that, every time it realizes that pin 7 went from Low to High it will trigger a combination change.

Aaand.. the Dir signal... It uses the RESET pin. No I have never messed with the fuses and I have not the intention too... There is a line somewhere in the Attiny85 datasheet that explains that the microcontroller will reset if pin RESET goes under 0.9V. This IS technically a Low signal. But what happens if the voltage is less than 5V (undoubtedly High signal) but more than 0.9V?

Step 5: Why It Works?

Picture of Why It Works?

Well after tests from the Arduino community forum, the threshold of resetting is higher than 0.9V. More like 2.5V. But, there is still space between 2.5V and 5V. As you have seen in the pinout, the pin 1 (Reset) isn't just a PORTB, IO capable pin, but an ADC0 pin. Meaning that it can read analog signals. Inbetween Low and High lay analog signals...

So using a (common NPN) transistor and a pullup resistor would make the analogRead() (arduino language) command read a High (1023) when the transistor is disabled (Voltage at Base 0V) and an almost High 685 signal when the transistor is enabled. Both signals don't reset the microcontroller. So we can read different things when the transistor base goes High and Low. Now if we connect transistor's base to the Dir signal we can be aware of both of its states by reading the Reset pin.

Step 6: The Code

Picture of The Code

Code. Not much... It is self explanatory and fully commented.

(Written on Linux, windows users may need to add some Returns (new lines) or change to Linux.

The later is a Solution, the first is conditioning)

Both "firmwares" use half stepping (8 state driving). "RT" stands for Real-Time.

The "non_RT" code ensures that there will be no lost step if you feed it with step signals up to 1200Hz. But it may not execute steps exactly after a signal. If fed with steps more than 1200Hz it will rotate the motor for ever (due to an overflow) and only a reset will stop it.

The "RT" code doesn't ensure a thing! It is significantly faster but may lose steps if given in high frequency (more than 2000HZ - possible that your motor will stall before reaching that frequency). The code includes some AVR libC inlines to make things faster.

If you try "general tinkering" use the "non_RT" firmware, if trying a CNC definitely use the "RT" one (don't worry about lost steps, easy-drivers and pololuswork the same way too).

/--------------------------------------------------------------------------------------------------------------------------/

You can use the DIY AVR Programming Station to program this puppy. It is an easy, cheap and damn useful build.

Step 7: Room for Improvement

Picture of Room for Improvement

Well, making this circuit in a perfboard, breadboard, PCB or anything else isn't always the end. You may want to improve the controller. Well, guess what? Take the Attiny from the socket put it in your programmer (whatever that is) and change its "stepper control firmware" as you like.

You can change the delay time (because it actually depends on the motor), the threshold (if you change the resistors), the stepping technique (you can do Full Stepping - now it is Half Stepping - or create a new one)...

You CAN'T change the Pinout though. You may write a Real Time controller too (this is not *that* real time) and control big CNCs (not only hobby ones). Finally you can, somehow (some software PWM I guess), add MICROSTEPPING. The sky is the limit. And if you get bored of it, just make your Attiny a traffic light controller and scrap the motor project altogether (don't forget, the Attiny is easily reprogrammable - even on circuit - no fuse change made)

This driver can receive a step High signal every 1500 us (microseconds - 1.5ms milliseconds) and not lose any step (while half-stepping). That is 0.0015 sec period. So 666.6... Hz.

If you do any significant changes or add features, just let me know!

The best way to do that isn't sending me an email, but making an instructable about it or commenting your added features and maybe code!

If this project gets enough improvement, I will open a SourceForge entry about it to let everyone have an *almost* free stepper controller-driver!

Share your work...

Thank you for reading my second Instructable...

Step 8: Oh, I Almost Forgot. COST

Picture of Oh, I Almost Forgot. COST

Why make something when it is cheaper to buy it...

This controller's first purpose is to be cheap. Really cheap:

Attiny85 - 1.80 euros

Female headers pins - 0.10 euros

3 1KOhm resistors - 0.03 euros

1 2n3904 transistor - 0.05 euros

perfboard - 0.30 euros (ebay)

And if we buy a ULN2003 (some cheap steppers come with their own drive circuit)

ULN2003 - 0.35 euros

or

L298N (2 Amp dual H-bridge, the most expensive I could find) - 3.20 euros

Well, it is about 2.5 euros or 3 bucks for a unipolar motor

and about 5 for a really beasty bipolar one(used on CNC wood Routers and such big things)...

Not 10 or 20 euros...

And microstepping is on the way... After that there will be no reason to buy a "Stepper controller"...

Comments

jbike (author)2017-05-13

Nice! Great tip on using the reset pin on the ATtiny85!

Pi3 (author)2016-11-24

Thanks for this... I gain a way how to program the stepper motor i have bought. :)

makinworks (author)2015-12-24

Is there a way to integrate this step motor system into another design system if I give you the plans and basic drawings?

It is for creating a motion picture film reel to reel scanner

Using a iPhone time lapse camera or a sale camera or even a flatbed scanner with a acute limited section enabled via software to scan at HDR resolution from old film or new developed film negatives

35mm, 16mm, 8mm
All have different step motor presets

So this is where your part of
How to control the Step Motor Reel to Reel chassis

This altogether could make a frame by frame film scanner that is low budget compared to the $250,000 USD ARRIscan
Or the black magic design $29,000

The Laywer is tempting but still the cost of a car

So if possible can we build this based upon this and other people's work! ? To make an off the shelf kit?

Thanks

john1a (author)makinworks2015-12-25

You sure can do that!
You need to specify the control unit you will be using. Is it a PC, a Raspberry Pi, an Arduino ?
If you assemble a stepper-controller, and give it step instruction from your control unit, you can make a motor spinning in no-time!

dandyvandy563 (author)2015-10-07

I programmed two attiny 85s and man it is amazing. Saved me soooo much money and time since I had 10 of them laying around from a couple projects and years ago and tons of transistors salvaged from different electronics. Great Great post. Thank you so much for doing this instructable.

padbravo (author)2014-06-21

I will give it a try...
I just got some swiss-made steppers (used, of course!, and cheap!) and want to try to make them work..
any ideas of how to use those TIP120 to allow for 1Amp? tks!

diy_bloke (author)padbravo2015-06-15

it is probably too late for you, but someone else may wonder.
very simple just use the outputs of the attiny that ar elabelled as 1,b,c,d in the functional schematic and send these to 4 TIP120's via a base resistor. as the hFE of the TIP120 is about 1000, I'd say a 560 Ohm- 1k base resistor would suffice. Tie teh emitters to ground and use the open collectors for the coils. Add a protection diode over each coil :-)

diy_bloke (author)diy_bloke2015-06-15

sorry, typo's:

use the outputs of the attiny that are labelled as a,b,c,d

diy_bloke (author)2015-06-15

that is indeed a nifty trick you are pulling there :-)
I slightly disagree though with what you said about the attiny not being able to be programmed once you meddle with the reset fuse.... simply reset the fuses back to factory state with a simple and cheap HV programmer. Anyway, great trick!!

grayl (author)2015-06-04

john1a:

johna1: In the last 10 lines of the first INO file in Step 6, where did
you define 'state[0], state[1], state[2], and state[3]? I cannot find
any previous reference to those values.

FellaMegaOld. (author)2015-02-14

I tried really hard to keep the tiny85 in the scope, alas it's not possible to microstep the 85 beyond 1/32 (without problems) in C , if i had more time assembly would be the best solution IMO. If you take a peek over @ the attiny2313 version that inspired you, i left a comment there. I believe 1/16 stepping is the sweetspot for the 85 as it hasn't missed or over/under shot a step in a 4 day test, 1/10th is the recommended by machinists.

Im trying to redesign a method that incorporates jumpers plus input on the reset (voltage division) so its possible to choose between 5 modes full,half,quarter,eighth & sixteenth plus direction from 4bit ADCH.

I can confidently say that 1/800th microstepping is possible on an attiny in C , but not with the 85 or 2313, looking through Atmel search the Attiny441/841 with four 16bit timers & two 8bit timers at 14 pins is the best choice.

Attiny--->Opto--->Mosfet

I consider my purchased $200 1/256 Drivers to be outdated bricks :(
There is a nice piece of coding on avrfreaks that is adaptable to the 85

http://www.avrfreaks.net/forum/finding-specific-av...

I believe everyone is inspiring everyone these days :)

john1a (author)FellaMegaOld.2015-02-14

I am glad you are really at it! I was thinking the Attiny 2313 (maybe we will need more flash memory though). The idea is to use the native PWM pins and some capacitors to normalize the signal to an acceptable point. I have tried all those with attiny85 and softPWM but it failed miserably because I had a pure (slow) PWM implementation. I am finally sure that this can be done with attiny85 - the same conclusion as you.

I have written a python  script that gets the type of microstepping (linear/sin-cos/custom), the number of steps and the phase difference and outputs a C array with the power levels (0-255) to use as PWM values.
If you want it I will embed it in the Instructable code page...

Cheers!

FellaMegaOld. (author)2015-02-12

It's hard to expand on this subject without the correspondence of the author :(

The lowest achievable step size is currently 1/512.

A complete rewrite manipulating registers directly in 1,238 bytes :)

john1a (author)FellaMegaOld.2015-02-12

Oh, I am almost full all this period (I am in college), I study really hard.
Well 1/512 is by half stepping the 64 steps (8*64).
I really want to learn hard AVR assembly. I never got really good at it.
If you have the version with direct register-manipulation please upload it in a comment or send it to me to upload it to the Instructable.

Thanks for keeping it alive. I have some ideas about making it a microstepper with about 1 more euro...

FellaMegaOld. (author)2015-01-15

A simple 22k resistor between VCC & RESET, 33k from input to reset builds a simple voltage divider, Negating the need for the transistor & 3 resistor by only using 2 resistors.

If the input is held HIGH, RESET=5V.

If the input is held LOW, RESET=3V.

* Some notes for viewers; Micro stepping is using digital electronics to achieve the equivalent of mechanical gear ratios. A stepper at full step with mechanical reduction does not lose steps, whereas the digital equivalent does, regardless of manufactured step drivers & claims!

* Micro stepping is no different than the toasting level on your toaster, the old toasters had 1 settings, the electrons in the wire/element where always aligned in the same path (path of least resistance) & the toaster lasted for a decade(s).

* Wife likes a white toast, level 1, son likes brown toast, level 3, Dad likes black toast, level 5, all this switching between currents forces new pathways to be introduced within the element at some point an atom begins to collapse causing a chain reaction. The final effect is a toaster that doesn't toast.

* Full Stepping = Maximum Torque & Longer Life, Higher Voltage = Faster Movement & Reduced Life, Gear Reduction = Finer Accuracy & Slower Movement.

* This is the coolest & most efficient driver you are seeing it's only limitation is how we can drive that nema42 bipolar stepper you saw on fleabay right? We want Maximum efficiency?

* My apologies to John for highjacking these posts :)

* L298 Dual Full Bridge Driver

http://www.st.com/web/en/catalog/sense_power/FM142/CL851/SC1790/SS1555/PF63147

Takes 5-46v** & delivers 4A.(google for circuits)

** Datasheets often push the boundaries of what is acceptable (most efficient & modest) these are theoretical, typical or ideal limits. Which in laymen terms means possible, probable or potential. I have one of those nema42 & the sweet spot is (24v 2A)*** , even though a myriad of datasheets & people say different things.

*** Chicken or the Egg, I read a long time ago about a Japanese way of DC Motor tuning. You take the motor and bolt down on a table, next to the motor you have a sizeable dish filled with water. As you apply voltage or current, the vibrations from the motor are passed through the table into the dish. We do not want the dish to move, we do not want the ripples to be choppy. What we want to see is that the ripples seem statuesque, as if they are frozen in place or near to it.

* I have found 24v 2A to be a sweet spot for almost every class of nema i have tested with coil/phase of 2A or greater.

* The 7805 voltage regulator is good, but i really suggest the lm2937-5 which is rated up to 26v input.

* And lastly for the adventurous, drop the l298 & find the LT1161 IC :)

Thanks for your patience everyone.

FellaMegaOld. (author)2014-12-16

SoftPWM

http://www.kobakant.at/DIY/?p=3393

int cycle = 10000;

void setup(){}

void loop(){}

void softPWM(int pin, int duty) { // software PWM duty is (% on) time
long dutyOn = (duty*cycle);
long dutyOff = (cycle*(100-duty));

bitWrite(PORTB, pin, 1); //on
delayMicroseconds(dutyOn);

bitWrite(PORTB, pin, 0); //off
delayMicroseconds(dutyOff);
}

FellaMegaOld. (author)2014-12-08

Read & Understand this;

http://startingelectronics.com/tutorials/AVR-8-mic...

With another micro (Attiny2313) we can use bitread() to check the state of the Step & Direction pins of (X), the possible states are 00,01,10,11 we can PWM values 0-255 on a single pin output for (x).

Realistically we are only interested in 2 states, 01 & 11, (Step forward & Step reverse) for now :)

The 2313 has (4) PWM pins, 3 pins per axis @ 3 axis = 9pins (6inputs & 3outputs) from 17 available io.

Leaving 8 possible inputs, 3 for x, 3 for y (8 states) & 2 for z (4 states).

**Note: "I have not needed a sampling rate greater than 1,000hz" should have read "

I have not needed a sampling rate greater than 1,000kHz"

FellaMegaOld. (author)2014-12-06

I hope this helps someone ? 10bit ADC is like getting 100 pennies, 8bit is like getting a Dollar, even though they are both the same thing, one has more precision.

The cost in converting an analogue signal to digital (100 pennies) takes more cycles & involves more maths on the processor.

Atmel recommends not to take 10bit samples at a frequency Greater than 1Mhz, what is not written is the precision of 8bit samples.

8bit samples go beyond the 1Mhz limitation :)

volatile byte curStep = 0;
byte coils[] = {0, 1, 3 ,4};

#define highThreshold 127

byte steps[8] ={
0b00100001,
0b00100011,
0b00100010,
0b00101010,
0b00101000,
0b00111000,
0b00110000,
0b00110001,
};
byte dead = 0b00100000;

void setup() {

DDRB = 0b00011011;
initADC();
}

void loop(){
//make sure we define result as a byte, no math required
byte result = 0;

//set ADSC pin to 1 in order to start reading the AIN value
ADCSRA |= (1 << ADSC);

//do nothing until the ADSC pin returns back to 0;
while (((ADCSRA >> ADSC) & 1)){}

//for 8 bit precision we can just read ADCH:
result = ADCH;

if (result >= highThreshold)
PORTB = steps[--curStep % 8];
if (result > 0 && result < highThreshold)
PORTB = steps[++curStep % 8];
}

void initADC (){

//Configure ADMUX register
ADMUX =
(1 << ADLAR)| //Use 8bit ADC
(1 << MUX0)| //Use ADC1 or PB2
(0 << REFS0)| //set refs0 and 1 to 0 to use Vcc as Vref
(0 << REFS1);

//Configure ADCSRA register
ADCSRA =
(1 << ADEN)| //set ADEN bit to 1 to enable the ADC
(0 << ADSC); //set ADSC to 0 to make sure no conversions are happening
}

john1a (author)FellaMegaOld.2014-12-07

Thanks for contributing to the project!
Please explain what exactly this code is doing. I sense you have made something great!

FellaMegaOld. (author)john1a2014-12-08

Instead of using extra components & avoiding the dreaded reset pin.

We can limit the amount of cycles taken & access the ADCH register directly.

So for example if it takes 13cycles to read an analogue value & convert it to a digital value 0...1023 , we can forgo the precision & directly read the byte without converting it, as a value of 0...255, as we are not needing the precision or need a scaling factor, just the bare analogue value of a single register(Not 2 registers ADCL/ADCH)

We can further push the boundaries of sampling by eliminating registers we do not need such as BOD "Brown out Detection" there are others depending on what your code needs to do.

I have not needed a sampling rate greater than 1,000hz , the reason for missed steps is the factor of time doing a 10bit conversion between coil states.

**Note: A single wire or free standing adc pin will inherit electromagnetic interference, to greatly reduce this interference we use insulated wire & ferrite beads.

john1a (author)FellaMegaOld.2014-12-08

Oh, I see! Yeah, I used the arduino library analogRead() that needs many cycles... It was used for simplicity. It isn't the best technique, but it worked!

You seem to enter the long path of optimization... You must have both guts and time!

Do you have any idea about soft PWM for microstepping? I have written some code but the slow softPWM I made myself makes the motors jog badly...

FellaMegaOld. (author)2014-12-06

I like what you have done :) I did similar, but waaay different :)

In loop take value of pb2 also catching interrupt to check value.

> value (step forward)

< value (step backward)

You can use many values for implementing micro stepping , no rst needed.

Extend with High Speed Optoisolator SOIC 16 , 60V 4A.

I hope this helps :)

john1a (author)FellaMegaOld.2014-12-06

Yeah but his way you have a non standard interface. The linuxCNC systems and MACH3 use the Step/Dir interface and this hardware is designed to work with linuxCNC.

But I am not sure if I understood correctly.

FellaMegaOld. (author)john1a2014-12-06

I missed this comment... oops!

My Nema42 stepper drivers are Attiny85, Im using GRBL on a UNO, I feed step/dir to an Attiny2313 which feeds the 85's.

In my first reply i generalized that you can take an adc reading & isr from the same pin, which is harder & seems (i steered away from this in the end).

I am not using xtal with the Attiny, the 85's are standard 8Mhz with a prescaler of 8 with BOD disabled.

I hope that clarifies things ?

john1a (author)2014-06-22

First of all you have to use TIP120 Array ONLY if you have a unipolar (5-6-8 wire motor). For 4-wire motor there are other things to use to drive them.

Sure you can use TIP120 for more than 750mA. It can handle even 5A but I just wouldn't push it to the edges like this.
I suggest the ULN2003 IC as it is more easy to use.

Please post photos of your work and (if you know programming) contribute with your code changes (if you do any)!

About This Instructable

27,148views

92favorites

License:

Bio: I study Computer Science and generally tinker with stuff. Be it software or hardware. I have my software periods and my hardware periods.
More by john1a:Repurposing my Laser CNC into a multi-tool CNCHow to make PCBs easilyHow to make your own AVR programming station for under 8 bucks
Add instructable to: