Attiny Motorboard

tinystepper

For 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-stepper

A 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 off 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.jpg
For 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 utilizing 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 energized 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. The program was written on the basis of the Smeezekitty core for the Attiny13. For the MCUDude microcore a small change is necessary, indicated in the program below:

/*
                                _____
                               |     |
 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
  byte servoPin=4;
 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 doesn’t 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));// this is no longer allowed in the Microcore
delay(5);// so we use this
digitalWrite(pin,LOW);
}

and call that like this:

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

Full program here.  (backup)

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 alertSmart-Electronics-28BYJ-48-5V-4-Phase-DC-Gear-Stepper-Motor-ULN2003-Driver-Board-for-Arduino

I 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.

I have a 3d file for a motorflange and housing for the commercial board avaiable.

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

Advertisement