Attiny Motorboard

tinystepperFor a project I needed to drive a steppermotor, a servo and possibly a small regular DC motor. Piece of cake of course with an Arduino, but I am anal retentive where it comes to  underusing an Arduino and as I had come by a couple of Attiny13A’s why not use those.
attiny-stepperA circuit is easily drawn up and doesn’t hold too many surprises. The chip of choice is the ULN2003 that can take 500mA per port. Driving a steppermotor for a while can make the chip unpleasantly hot and adding a heatsink is a wise precaution. My Steppermotor, the 55SI-25DAWC (1350 g/cm torque) has a 6 prong connector with the two  midconnectors that receive the  Motor Voltage on one side and the 4 coil connectors next to that, so that kinda dictated my design on K1. It is 36 Ohm at 12 Volt, so  each coil  uses 333mA.
The servo connector K2 is rather standard: Signal-Vcc-Ground. The DC motor connector K3 is fed by the open collector output of the ULN2003. The signal for that is shared with the Servo, as for now I probably wont be using both, but If I need both, I might be feeding it of  PB5, though that would mean resetting the fuses to disable the reset that is attached to pin1. It also means I need a high voltage programmer if I need to  reprogram the chip.
tinystepper-stripboard

A prototype is easily set up on a piece of stripboard. The interruption of the second strip between F and G is just there in case I want to add a jumper to switch between servo use and ULN2003 use on Output Q3. Rather than making K3 just a two prong connector, I decided to add  an entire row that is connected to V++, so if I so wish, I can also use  Q1-Q7 just for  DC motors. It gives a bit more flexibility. As the Attiny13 has a max of 6 I/O pins and the ULN2003 has 7 drivers, one can always decide to  use the drivers in parallel to drive bigger loads.

Programming:
The Attiny13  has only 1 kByte available, but that is enough  for a simple application with a servo and a steppermotor.
As my steppermotor is a rather old one already, I doubt if too many people have it. so my program is most likely no use  for anybody else, but driving steppermotors is rather easy.
With the unipolar steppermotor that I use, there are 3 ways of driving it: Halfstepping, Full stepping or wave driving
Wave driving is the easiest: you just make each pin high in the right sequence.
coils.jpgFor a unipolor motor that would be: 1a-2a-1b-2b. That would spin the motor in low torque because there is always a moment in which there is no coil magnetized.
Half stepping requires alternating between energising a single coil and two coils at the same time. This increases the angular resolution, but the torque fluctuates between utilising a single coil and both coils.. In principle though it means that you keep one coil magnetized while you already switch on the second one. So that would be:
1a-1a2a-2a-2a1b-1b-1b2b-2b-2b1a,
Full stepping is when two coils are always energised at the same time. This allows the maximum torque of the motor to be used, at the expense of more current. This looks like:
1a2a-2a1b-1b2b-2b1a.
For completeness sake: the 55SI-25DAWC can also be used as bipolar stepper motor just by not using the white wires. This gives more torque and less power consumption
The below program is just a quick illustration of how to drive a stepper in Full stepping mode:

/*
                                _____
                               |     |
 Hardware:             +5V     |     |
             ________   |      |     |     
      ___   |        |  |      |     |  ___  
 +5V-|___|--|RES  VCC|--+   B3-|I4 O4|-|___|-+Q3 brown
            |        |         |     |  ___  
        B3--|PB3  PB2|---------|I5 O5|-|___|-+Q2 yellow
                     |         |     |  ___  
          --|PB4  PB1|---------|I6 O6|-|___|-+Q4 blue
            |        |         |     |  ___  
         |--|GND  PB0|---------|I7 O7|-|___|-+Q1 red
            |________|         |     |       
             ATtiny13        |-|GNDCC|------- +12Volt white
                               |_____|    |__ +12Volt white
                                ULN2003 
Funktioning: sequence: red-yellow-brown-blue
    Stepmotor drive sequence and encoding:
      Portbit      PB0   PB1   PB2   PB3   |            |
      Color         rd    bl    yl    bn   | Portbit    | Byte
      Step          O7    O6    O5    O4   | 3  2  1  0 |
      -------------------------------------+------------+------
         1          1      0    1     0    | 0  1  0  1 |  05
         2          0      0    1     1    | 1  1  0  0 |  12 / 0C
         3          0      1    0     1    | 1  0  1  0 |  10 / 0A
         4          1      1    0     0    | 0  0  1  1 |  03
If you would use D8-D11 on an Atmega328, you could use the same values 
for the Portbits, as D8-D11 is equivalent to PB0-PB3

Coils
 red    ------------+------------ brown
 yellow-------------+------------ blue
 */
 #define delayTime  200// time between steps
 void setup()
 {
 DDRB=31; // set Port 0-5 as output
 }
 void loop()
{
 stepper(3); //=90 degrees. The angle is 7.5 degr,=> 4 steps=30 degr.
 }
 void stepper(byte turn)
 {
 for (byte pos=0;pos<turn;pos++)
 {
 PORTB=5;
 delay(delayTime);
 PORTB=12;
 delay(delayTime);
 PORTB=10;
 delay(delayTime);
 PORTB=3; delay(delayTime);
 }
delay(1000);
 }

The above program is just rough, to show how to drive a stepper and it misses some  sophistication. Writing directly to PORTB is OK, but in this case it will also write a “0” to PB4 and PB5. PB5 is not much of a problem, but you may want to use PB4. In my case that is where I put my servo and that doesnt really cause a problem as I do not use them at the same time.
If you want to avoid writing to PB4 and PB5, use a mask to only write to bit 0-3. The mask to do that is B00001111.
If you then want to set bits bits 0 and 2, go like this:
PORTB=(PORTB &~mask) | (B00000101);
For those who find this too cryptic:
it  first ANDs the value of PORTB with NOT mask and OR’s the result with the value we want to write and assigns that back to PORTB.
So, suppose PORTB= 00010000 and we want to write 00000101 to it, we cannot assign that immediately because that would clear PB4.
However, if we do as described, it becomes:
PORTB=(PORTB & 11110000) | 00000101
PORTB=(00010000 & 11110000)  | 00000101
PORTB=00010000 | 00000101
PORTB= 00010101
We have written our value and kept PB4
So, why cant we immediately OR PORTB with the value we want in stead of AND-ing it first?
Well because  that might keep PB4 and PB5… but it also keeps PB3-PB0 unchanged if  one of them already contained a ‘1’
Of course inverting the  mask wouldn’t be necessary if we would define it already inverted, but it is common practice to do it as such

Writing to the Servo is quite easy:
add this  function:

void pulseOut( byte pin, byte p){
digitalWrite(pin,HIGH);
delayMicroseconds(300+p*(2500/180));
digitalWrite(pin,LOW);
}

and call that like this:

for (byte pos=0;pos<180;pos++)
{
pulseOut(servoPin,pos);
delay(20);
}

High Torque mode uses more power than low Torque mode. In Low Torque mode each step in my case (12V, 36 Ohm coil resistance) takes 333mA. In high torque mode, each step takes 667mA (2×333.33).

In case you are wondering what project I needed it for: I need  a doll to turn and  nod its head.

Self build alert
Smart-Electronics-28BYJ-48-5V-4-Phase-DC-Gear-Stepper-Motor-ULN2003-Driver-Board-for-ArduinoI enjoy building stuff, but it isn’t always the wisest thing to do. There is a ULN2003 based driver board, including a good steppermotor available for about 1.80 euro. That is a good deal. In my case, I  just wanted the Attiny13 and ULN2003 driver to be on one PCB, I already had a spare ULN2003 and I had the steppermotor so that was a no brainer, But for anybody else wanting to  drive a steppermotor, consider that cheap motor and driver.
My cost for just the driver section (chip,  pins, socket), I estimate 45 ct (euro). Not sure what my stepper costed me 30 years ago, but a decent hobby stepper now will be between 1.60 euro and 5 euro, so the savings in  self built (not even counting the solder and electricity use) are minimal to non existent. So only do it for fun, educational purposes or if you need something tailored like i did.

That trusty Attiny13
Finally I have to praise the Attiny13 for being extremely resilient. Due to some stupidity from my side, I connected PB3 with O4 instead of I4, So it received 12 Volt through a 36  ohm resistor and also tried to drive a 330mA motor coil. This situation lasted for at least a week in which it would sometimes be  steering the stepper for hours, with me  trying to find out why it wasn’t working optimally.
I only found out when I accidentally felt the chip was getting pretty hot.
I fixed the connection and  the chip was still working (and the motor turned better). A week of 12 Volt on one of its pins and getting hot and still working great

Advertisements

Servo on Attiny13

Wanted to use an Attiny13 to sweep a Servo. There is an 8 bits Servo library for the Attiny85 series, that will compile after  some changes (TIMSK->TIMSK0 and TIFR->TIFR0) but that will be over the memory limit of the Attiny13, some other programs I found that were playing directly with the timing registers didn’t really work and one even broke the gears on my servo, so I decided to just make  my own program, which is in fact much simpler than I thought once I started:

byte s=0;
void setup() {
pinMode(s, OUTPUT);

}

void loop() {
for (byte pos=0;pos<180;pos++)
{
pulseOut(s,pos);
delay(20);
}
}

void pulseOut( byte pin, byte p){
digitalWrite(pin,HIGH);
delayMicroseconds(300+p*(2500/180));
digitalWrite(pin,LOW);
//Serial.println(p*(1000/180));
}

The line “delayMicroseconds(300+p*(2500/180));” needs a bit of explanation:
“p” is the position in degrees, so if “p” is ‘0’, the pulsewidht for 0 degrees is sent to the server. In this case that is 300 uS. if p=180, the value for a full sweep is sent to the servo. In this case that is 2800uS.The values of 300 and 2500 are experimental: I started out with 1000 and 1000 but then the servo turned only some 90 degrees. Some programs for Attiny85 mention 60 and 4000uS as the min and max values for the pulse width
As  the values are  experimental, it doesn’t really matter if the  timing of the delayMicroseconds is off a bit on the Attiny13 core, but they seem OK for a UNO as well.
Though only a few lines, it still takes 540 bytes on the Attiny13.
True, due to the use of ‘delay’ the processor will mainly be ‘waiting’. Ofcourse one can solve this by using millis, or by setting up a timer, but it is an Attiny13…. there really isnt so much memory space to cramp a lot of other programming in it anyway, so sweeping the servo is the core  function.

Identifying and using a stepper motor on Arduino

If you buy a new steppermotor for a project there is usually some documentation telling you how to connect it.
However, we do not always buy steppermotors with documentation: sometimes you have an old one, sometimes you pull it out of an old unused device or get it from a surplus store.
P1040286

I found a steppermotor that I had probably bought 30-35 years ago and never used (over ambitious). It did not offer much info other than: 55SI-25D AWC 7.5 DEG 36 Ohm and that it was from Oct 83 and came from Japan. It had six wires, but other than some handwritten labels mentioning colors and numbers (that were even corrected), it offered no clue on what connection was what. Initially, also the internet offered no help other than some questions about that type of motor (Although I recently found some info).

So, how to identify what was what? Well first the number of  connections –6-   (brown, yellow, blue, red, white and white) suggested it was a unipolar steppermotor and I suspected the two white ones to be the common connection. To establish how the rest of the wires where connected it was time for the multimeter and I set up a small table in which I could enter the resistance values I measured:

white 1 white 2 red blue yellow brown
white 1 x 36Ω 36Ω
white 2 x 36Ω 36Ω
red 36Ω x 72Ω
blue 36Ω x 72Ω
yellow 36Ω 72Ω x
brown 36Ω 72Ω x

For those having trouble reading the symbols: ∞ means that there was an infinite resistance (i.e. not connected) and x means that there is no need to measure it as it is the same wire.

If you don’t have a multimeter, it becomes a bit harder but then you can also find which coils belong together: if you short a coil the resistance in manually turning the axis increases

unipolarcoilsObviously this was a motor with 4 coils, that each have a white common connector and the table tells us that red and brown are the coils connected to ‘white 1’ and that yellow and blue are the pair with ‘white 2’ as a common connector.

However, with a unipolar stepper the coils need to be driven in a certain sequence, otherwise the motor won’t turn at all, or will have only little power and though from the table we now know what coils belong to a pair, we still do not know what the sequence of the coils is.

In other words take for instance the red and the brown pair. Is red coil 1 and brown coil 2 or is it the other way around?  Well, that is a bit tricky because even the numbering of the coils is not always standard.

There is a way of measuring which coil is which, by applying voltage to one coil and then adding voltage to another coil, while feeling if the shaft turns at all and what way. But that is actually just as much work as connecting it to an arduino and switching a few pairs of wires to test. Once you have established –as we did in the table above-  what pairs are connected. It is really not that much work anymore.

coilsSo for now let’s forget about coil numbers and look a bit more at the functions and how to drive the coils.
So, for the time being we will just call them coil 1a,1b, 2a and 2b. we don’t know which one is a and b but we do know that it is the red-brown pair vs the blue yellow pair.

As none of the coils belonging to the same pair should be energized at the same time, the sequence must be either:
red yellow brown blue
or
red blue brown yellow.
As it turns out, it is red-yellow-brown blue to turn the motor clockwise and yellow-red-blue-brown to turn the motor counter clockwise

There are in fact 4 ways of  driving a steppermotor:

  • Wave driving (sometimes also called (“one-phase on, full step” ) is the simplest as only one coil is on at any one time. This uses least current but also produces the least amount of torque. The coil activation sequence would be: 1a-2a-2b-1b-1a etc
  • Half stepping is done by alternating between activating a single coil and two coils at the same time. Due to the smaller step angle, this mode provides twice the resolution and smoother operation. Half stepping produces roughly 15% less torque than dual phase full stepping. Modified half stepping eliminates this torque decrease by increasing the current applied to the motor when a single phase is energized. The torque fluctuates between utilising a single coil and both coils. the coil activation sequence would be:
    1a-1a2a-2a-2a1b-1b-1b2b-2b-2b1a,
  • Full stepping (sometimes also called  “two-phase on, full step”) is when two coils are always energised at the same time. This gives the motor maximum torque but will require more current more current. This looks like: 1a2a-2a1b-1b2b-2b1a.
  • Microstepping is a technique that increases motor resolution by controlling both the direction and amplitude of current flow in each winding. Current is proportioned in the windings according to sine and cosine functions. Microstepping is at the expense of drastic loss in torque. On the Arduino microstepping can be achieved  with PWM. However, unless you really need it, I wouldnt bother

To drive the motor continuously, we just apply power to the two windings in sequence. Assuming positive logic, where a 1 means turning on the current through a coil, the following two control sequences will each spin the motor clockwise 24 steps:

  Winding 1a 1000100010001000100010001
  Winding 1b 0010001000100010001000100
  Winding 2a 0100010001000100010001000
  Winding 2b 0001000100010001000100010
              time --->

  Winding 1a 1100110011001100110011001
  Winding 1b 0011001100110011001100110
  Winding 2a 0110011001100110011001100
  Winding 2b 1001100110011001100110011
              time --->

Note that the two halves of each winding are never energized at the same time. Both sequences shown above will rotate a permanent magnet one step at a time. The top sequence only powers one winding at a time, as illustrated in the figure above; thus, it uses less power. The bottom sequence involves powering two windings at a time and generally produces a torque about 1.4 times greater than the top sequence while using twice as much power.

Anyway, a simple program to test the motor would be:

int motorPin1 = 8;
int motorPin2 = 11;
int motorPin3 = 10;
int motorPin4 = 9;
int delayTime = 500;

void setup() {
  pinMode(motorPin1, OUTPUT);
  pinMode(motorPin2, OUTPUT);
  pinMode(motorPin3, OUTPUT);
  pinMode(motorPin4, OUTPUT);
}

void loop() {
  digitalWrite(motorPin4, LOW);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin1, HIGH);
  delay(delayTime);
  digitalWrite(motorPin1, LOW);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin3, HIGH);
  delay(delayTime);
  digitalWrite(motorPin1, LOW);
  digitalWrite(motorPin4, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin2, HIGH);
  delay(delayTime);
  digitalWrite(motorPin1, LOW);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin4, HIGH);
  delay(delayTime);
}

Now you cannot of course run the motor directly from the arduino ports. You can do this with special Motordrive IC’s like the L298D or with discrete components such as power transistors or FET’s, but a fairly cheap and simple IC that can be used is the ULN2003 darlington driver (or the MC1413).

A note though: with 6 wire unipolar steppermotors you can decide to forget about the  middle connectors (the ‘whites’ in this case) and drive them like a bipolar. That is something you cannot do  with a ULN2003, you need an H- bridge for that

If you do not know the voltage of a motor, then just start with 5 Volts and go up. Many steppers are actually 12 V. The ULN2003 can take 50 Volts and deliver 500mA per gate. As the motor I use has a coil resistance of 36 Ohm and the Voltage is 12Volt, that will be 333mA so that should be OK. Nevertheless, if you plan on using the motor at high speed, some cooling of the ULN2003 might be a good idea. There are DIL heat sinks available but you could also epoxy a piece of copper or aluminium U-tube on it. The ULN2003 is not the most efficient chip and the Darlington has a high voltage drop. The chip therefore dissipates a lot of energy.

Wire it up as follows:

uln2003-test

The connections of the header are chosen as above since that was the sequence of the header on the motor (but remember red-brown are a pair and yellow red are a pair).

On using the test program above, the following connections would make the motor step properly:

D8-> red
D11->brown
D10->yellow
D9->blue

This seems as one would expect coz it is the 1a,2a,1b,2b or at least the 1x2x1y2y sequence. Similarly, one would expect that

D8 –>red
D11->blue
D10->yellow
D9->brown

(basically switching ‘1’ and ‘2’)  would make the motor step backwards and it does.

When the motor is used with the ‘Stepper.h’ library from the Arduino (e.g. in the Tom Igoe “Stepper_oneStepAtATime”), we see the same results.

For those interested to try the stronger torque program and try some direct bit manipulation at the same time have a look here:

As the steppermotor takes up 4 of the 7 outputs, you may want to consider using the other 3 to drive relais or a couple of small dc motors. The outputs of the ULN2003 may be parallelled for higher output current. The 3 darlington’s left therefore could drive a 1.5 Amp load.

If you need to drive two steppermotors consider the 2803 as that contains 8 darlington drivers rather than 7.

However, there is something else you can do with the spare gates, Remember the stepping sequence t o drive the motor?

Steps Coil 1 Coil 2 Coil 3 Coil 4
1 1 0 1 0
2 1 0 0 1
3 0 1 0 1
4 0 1 1 0
1 1 0 1 0

There is a pattern in this table: Coil 1 is always the opposite of Coil 2 and the same goes for Coil 3 and 4. It is therefore possible to cut down on the number of pins from the Arduino (or other microcontroller) to just two, by using additional NOT gates.

The ULN2003 can provide these:

uln2003-2lines

Programming then is very easy by toggling the two pins high and low.

If doing work with the Arduino and a stepper motor, consider AccelStepper as a library. It is more flexible.
MOTEUR55SI
Good site here (Spanish) and translated

Driving an Attiny? or here.
here
Steppermotor wiring.