Yet another new Bit ... (stepper motor)

I am diligently working on my People Counter (aka CO2 sensor), but I needed a bit-break! So here is my Stepper Motor Bit:

This project is built around an ATtiny85 microprocessor, running a small, 5 volt stepper motor, the ubiquitous 28-BYJ48 that is available from many sources including Fry’s, RadioShack, Adafruit, and other hobby electronics dealers. A darlington transistor array (this device uses an NTE2019, but any 20XX series will work) is employed to provide the power to the motor. Pulses on the signal line direct the motor to turn either clockwise or counterclockwise. each pulse corresponds to a single step, making this motor more precise than any other littleBits motor.

As you can see in the video, the input voltage controls the direction of the rotation. The frequency of the pulses determines the speed (although the motor’s speed is one area that can be improved on!) Input pulses less than 1.6 volts stop the motor, 1.7 through 3.3 volts turn it counterclockwise, and 3.4 to 5 volts turn it clockwise. This means the motor can be controlled with an analog circuit (like in the video) or more complex control can be accomplished by using the Arduino bit (or other digital input) to provide the control pulses.

Here is the wiring diagram for this device from my notebook:

The ATtiny85 microprocessor packs the processing power of an Arduino in a very small chip. The tiny85’s software is derived from the 4tronix driver combined with the Arduino example code for State Change Detection:

/*    
 Stepper Motor Bit for littleBits    
 using a tiny85, NTE2019 and 28BYJ48    
 
 version 1: 15 May 2015 clh     

 */    
    
 // ------------------------------------------------     
 
 // analog input pulse pin:    
const int pulse = A2;    

// identify the motor pins - the motor has 5 wires:    
const int motorPin1 = 0;    // Blue   - 28BYJ48 pin 1 arduino pin d0, tiny pin 5    
const int motorPin2 = 1;    // Pink   - 28BYJ48 pin 2 arduino pin d1, tiny pin 6    
const int motorPin3 = 2;    // Yellow - 28BYJ48 pin 3 arduino pin d2, tiny pin 7    
const int motorPin4 = 3;    // Orange - 28BYJ48 pin 4 arduino pin d3, tiny pin 2    
                            // Red    - 28BYJ48 pin 5 (VCC)    

// variables:    
int pulseState = 0;         // 0 = 0 to 1.6v; 1 = 1.7 to 3.3v; 2 = 3.4 to 5v    
int lastPulseState = 0;     // previous state for pulse edge detection    
    
int motorSpeed = 800;  // variable to set stepper speed in µs (0.0064 seconds/pulse)    
    
// bit patterns of the coil energizations:    
int coils[8] = {B01000, B01100, B00100, B00110, B00010, B00011, B00001, B01001};    
    
// ------------------------------------------------     
    
void setup() {    
  //declare the motor pins as outputs, pulse pin as input    
  pinMode(pulse, INPUT);    
  pinMode(motorPin1, OUTPUT);    
  pinMode(motorPin2, OUTPUT);    
  pinMode(motorPin3, OUTPUT);    
  pinMode(motorPin4, OUTPUT);    
}    
    
// ------------------------------------------------     
    
void loop() {    
    
  // read the input pin and calculate the state (0, 1 or 2):    
  pulseState = analogRead(pulse);    
  pulseState = pulseState / 341;   // divide the 0-1023 input range into thirds    
    
  // compare the pulse's state to its previous state    
  if (pulseState != lastPulseState) {    
    
    // move the motor based on the pulse voltage    
    if (pulseState != 0) {    
      if (pulseState == 1) {    
        anticlockwise();    
      } else {    
        clockwise();    
      }    
    }    
  }    
      
  // save the current state as the last state, for next time through the loop    
  lastPulseState = pulseState;    
}    
    
// ------------ subroutines ---------------    
    
//set pins to NTE2019 high in sequence from 1 to 4    
//delay "motorSpeed" between each pin setting (to determine speed)    
void anticlockwise()    
{    
  for (int i = 0; i < 8; i++)    
  {    
    setOutput(i);    
    delayMicroseconds(motorSpeed);    
  }    
}    
    
void clockwise()    
{    
  for (int i = 7; i >= 0; i--)    
  {    
    setOutput(i);    
    delayMicroseconds(motorSpeed);    
  }    
}    
    
void setOutput(int out)    
{    
  digitalWrite(motorPin1, bitRead(coils[out], 0));    
  digitalWrite(motorPin2, bitRead(coils[out], 1));    
  digitalWrite(motorPin3, bitRead(coils[out], 2));    
  digitalWrite(motorPin4, bitRead(coils[out], 3));    
}    

Here is the test circuit used for the example:

Note that the USB power bit is used. This stepper motor is power hungry (as is typical for stepper motors.) While it will run from a battery, it draws more than 200 milliamps.


The major area this bit needs improvement is the speed of rotation. I plan on refining the software, but any help you may have for me will be greatly appreciated!

4 Likes

Hi @chris101,
Congratulations with this bit development ! Nice !
Two things popped up in my mind:

  • What do you think is wrong with the stepper speed of rotation ? If it should be faster maybe you could double the clockwise and anti clockwise program lines in the software ? Then it moves 2 steps on one input pulse… ( I think).
  • What would be the best solution to detect the position of the stepper motor arm, through a light sensor or by counting the pulses ? For counting you would need the existing Arduino bit to steer the stepper motor…
    Can the light sensor stop the motor or is this not possible anyhow ? :smile:
1 Like

Thanks @alexpikkert. This is the first project I have done using the Tinies, thanks to you, @JackANDJude, @codewizard58, @br1wr2el3, @syedBits, @Philip_Verbeek, @henrique007, and especially @StuckInSynth. Y’alls guidance, encouragement, and insightful questions have lead me along this path, and I like it!

Addressing your ideas - the speed of the motor is governed by the software I’m using to drive it. I think I could reduce the number of steps without losing any positioning precision, as it’s taking eight internal pulses per step instead of four. This makes it run more smoothly though. However, when I just run the motor, or even sweep it back and forth, it runs MUCH faster, so I think the multiple nested IF statements that I use to decode the voltage/direction data is soaking up a lot of cycles. I’m pretty sure better programming can help a lot here (although I’ve been programming on and off for nearly half a century, I am a ‘C’ noob.)

Positioning stepper motors is always an issue, since there is no internal sensor as there is in a servo motor. Yes, external processing (eg the Arduino bit) can easily count the steps, but the issue of where it started remains a challenge. I like your idea of a light sensor - perhaps an optical encoder attached to the shaft would work, Or maybe something as simple as the roller switch could tell the circuit where the motor is.

1 Like

Hi @chris101,
From earlier discussions I have seen that you can speed up the ATtiny clock cycles, maybe that will help ?
Detecting the shaft position could be done with a miniature magnet and a small reed-switch, although this needs again another bit development because there is no switch input bit…

A proto bit and a resistor can make a switch input bit. Remove the center jumper (data) and use the switch between in and out or between out data and gnd or +5

Yeah, I have a proto bit, and they are VERY useful! I use mine to measure current as well as move the lines on and off the main circuit. The jumpers are sheer genius! I like the cut wires for easily attaching a breadboard, but they are not so useful when you need to deal with in and out in a complementary fashion.

Good work @chris101, coding along just fine on the ‘Tinys’ I see…
First, work out your “step-counting” device, I like @alexpikkert’s idea, but a reed switch may not be fast enough. A super simple IR Send/Receive setup would detect the beam passing nicely. The problem here is that your traditional stepper motor control virtual always relies on a rotary position encoder of some type. Just counting a revolution may not get you any further, without counting a more significant value(so many degrees, ect.). The other more common than you’d stake your reputation on problem I think is assuring your field coils are wired correctly, polarity observed, phase observed. Might seem very straightforward, but I’ve never seen motor info that translates well to English(sorry about any stereotypes!). I know from experience that just because it is turning CW & CCW doesn’t mean it is proper. Phases working against each other could be your problem. As far as your code goes, I don’t think the if statements were out of hand, but I’ll post a link to a possible alternative, switch/case is really the best way I’ve found to execute code. No guarantees this works in your specific application, but coding is verified. stepperCode.ino BTW, if you’ve been programming for this long, just think back to the TRS(trash)-80, or even the first Apple/Apple II… DOS, BASIC, ect. all essentially complied to ‘C’
Happy Coding!
@StuckInSynth

2 Likes

Hi @StuckInSynth @chris101,
I am not sure which switching frequency is needed for proper detection of a stepper motor position. Which speed are you thinking of ?
I found some general information on reed switches (on the internet as usual), on page 50 a switching frequency of 500 Hz and an operating time of 0.3 msec are mentioned…

2 Likes

I’d say frequencies in that range are multiples of what is needed, more wondering if the ATMega can deal with the inductive “flutter” for lack of a better term, i.e. can it provide a usable signal?

Well, I did it!

I submitted my prototype of this bit - er, module - this week:

It is a simple implementation. This is breadboard prototype no. 3, and it has lots of issues. I am looking for some “official” feedback from @syedBits (it was very nice to meet you last Wednesday!) and any other littleBit technicians and engineers, and most of all, those of you in the forum who have been following this project, and community hardware projects in general.

I used the stuff we discussed in the op-amp thread, @vanessa & @JackANDJude’s ‘New to You’ thread, Jude & @StuckInSynth’s (Ryan’s) ATtiny thread, and @br1wr2el3 (Bruce’s) ‘Robot Arm’ project. I looked hard at @alexpikkert’s reed switch, but went with a rotary-optical encoder (made from Legos), and kept the position sensing external to the module. For musical inspiration, I read @leo’s Syntheory of Elements and bought a PO-14 micro-synth. What a fun toy! I used it for the background music in this movie:

For those wanting to look further, here is a ‘littleBits style’ schematic of my module.

Your feedback and ideas are important to me, and to the further development of this circuit. Thank you for all your help so far!

4 Likes

Hi @chris101,
Great ! I hope it will be published in the bitlab soon for voting…
Can you detail on the “lots of issues”, then I will try to see if I have some suggestions for you…

1 Like

Thanks @alexpikkert!

When I hook it to an oscillator and a slide dimmer, it moves smoothly and quickly (10rpm-ish) in either direction, depending on the voltage of the pulsed inputs. That’s great, just how I designed it.

But then I want to hook it to an arduino for programmability. So I program my Arduino bit to output a stream of pulses, 5 volts for forward, and 2 volts for backward, and set the switch on the Arduino to “analog”. It acts crazy: reverse works fine, but the best forward I can get is real herky-jerky. This is because the ‘analog’ output of the littleBits Arduino is PWM - even when the little switch is set to “analog” it still comes out as a series of pulses. And the resultant voltage is barely enough to get to the forward control voltage for part of the pulse. So it bounces back and forth.

(I don’t have an oscilloscope, but I can see the waveform, by using my 10 segment bargraph and moving my eyes back and forth rapidly. Ok, it looks strange!)

PWM is about 500 Hz, and the optimum driving frequency for full speed is about 200Hz. This isn’t much difference, so I’ve been using an online filter design tool to come up with an RC combo with just the right cutoff frequency…

The problem then becomes that when I effectively filter the pwm, but not the drive pulses, the voltage drops to where it won’t tell the module to turn forward.

Now I am exploring using an op-amp (here we go again!) to boost the signal back up where it should be. Like the circuit shown on this page. I won’t have a chance to work on this (or anything) for a week after today, so I am keeping careful notes, so I don’t have to redo it all again next week. :tired_face:

@chris101, I look forward to voting for this module, and I love how you pulled from all the resources that have been flying around lately! This is turning out to be an incredibly supportive community. :slight_smile:

I’m curious about how the lego rotary-optical encoder feeds back into the Arduino and how your stepper motor module would work with bits other than the Arduino module.

@pcc (Peter), come look at Chris’ video :arrow_up: . A stepper motor bit would greatly improve the accuracy of a debonair drawing robot, don’t you think?

2 Likes

Thanks @JackANDJude!

The optical encoder is a littleBits circuit:

usb power -> rgb led -> wire -> light sensor -> threshold -> (a1)arduino(d5) -> stepper .. arduino(d9) -> bright led

The light sensor and LED are positioned so that the disk attached to the stepper is between them. There is a small hole in the disk. At one point in the rotation of the disk the hole lets light from the LED hit the light sensor (I have the LED tuned so it’s got a lot of blue, and a blue filter is taped over the sensor - this keeps the room lights from activating the light sensor.)

When the light sensor is off, the Arduino sends out a stream of pulses and turns the motor. When the light sensor is triggered, it sends a pulse to the Arduino telling it to flash a second LED and pause the motor. After a few seconds, the Arduino starts the motor moving again, and it makes another circle, until the hole lines up again.

The motor works very nicely with analog control (no Arduino.) Here it is with a Korg oscillator bit driving it:

2 Likes

Hi @chris101,
Can you send me the Arduino ino file and the bit setup you used, I have an oscilloscope, maybe I can catch the waveform coming out of the Arduino for you.
Unfortunally I have no stepper motor, but maybe this will help to clarify things.
My basic thoughts about a stepper motor:
I am curious how a stepper motor ( a very good addition to the Littlebit system I think) can work nicely with other bits.
I can see there are two parameters to control this motor, speed by pulse frequency and direction by pulse amplitude.
Littlebit only has one SIG line to receive/send information.
Maybe one parameter could be set on the bit with a turning knob (speed ?) and the other via the SIG line (direction ?)
The most versatile design is indeed controlling via the Arduino, when the PWM issue can be solved…
Did you try using the Littlebit Synth oscillator to generate the pulses needed?

Hey Alex,

There are two sketches: 1) is running on the Tiny85 that is controlling to motor directly. That sketch is (mostly) unchanged from the one in the first post of this thread - well, the only change is to set the variable int motorSpeed = 1200; instead of 800.

The sketch running on the littleBits Arduino module that is sending pulses to the motor bit in my test setup is as follows:

// Stepper Project
// v1 5/25/2015
// v2 5/30/2015

// ------ declarations ----------------------------

// stepper motor module is on pin d5
   const int theMotor = 5;

   int motorSpeed = 10; // 3 is fast, 25 is slow


// ------- setup ---------------------------------

void setup() {
  // put your setup code here, to run once:
  pinMode(stepperMotor, OUTPUT);
}


// -------- main --------------------------------

void loop() {
  // put your main code here, to run repeatedly:

  for (int i = 0; i < 512; i++)
    {
      forward();
    }

  for (int i = 0; i < 512; i++)
    {
      reverse();
    }
  }


// --------- sub -routines --------------------

void forward() {
  analogWrite(stepperMotor, 255);
  delay(10);
  analogWrite(stepperMotor, 00);
  delay(10);
}

void reverse() {
  analogWrite(stepperMotor, 80);
  delay(10);
  analogWrite(stepperMotor, 00);
  delay(10);
}

The littleBits chain is just the arduino into the motor:

power -> arduino(d5) -> stepper

The setup for the thing that stops and flashes is a bit more complex, but I left all that out for working on circuit modifications. If you want to see it, look here.

I agree with you that sending two things on one SIG line is a problem, however I want to stay away from hardwired controls on the bit itself, but if that was necessary, then motor speed would be the one to wire in. That way, the input voltage (for direction control) would not need to be pulsed, however programatic control of the speed would be lost, which (imho) would reduce the utility of a stepper.

ps, yes, that is a Synth kit oscillator in the video right above your last post. :arrow_up:
It works perfectly.

1 Like

I really like the one input design you have for this module, @chris101. Thanks for showing me a non Arduino setup. I have a couple more questions for you:
Is the signal changed going out of the stepper motor?
What projects do you imagine people would most enjoy making with a stepper motor bit?

Hi @chris101,

I loaded your ino file into my Arduino and got an error message.
I suppose in your declaration part the constant “theMotor” must be “stepperMotor”…
I changed this and it worked.
I connected my oscilloscope on D5 via the protobit and see the result for the forward and reverse pulses:

Forward:

Reverse:

Both flanks on the 5V (255) and 2V (80) pulses are not steep ( I dont know if this is needed) and the reverse pulse has ugly top parts where maybe the stepper motor goes haywire…
Hope this clears thing up a bit for you…


2 Likes

Thank you Jude!

The output passes through unchanged. Use it? You mean as something other than to keep me busy? :wink:

One project I had in mind for it is a laser scanner, you know, like in the grocery store? I have an 8 sided prism that eventually I will attach to the shaft. Then knowing the step the motor is on will let me calculate the dot’s position.

And of course robot wheel driving. And, and, … (I’m typing on my girlfriend’s Kindle, so I should stop now :wink: )

2 Likes

Wow @alexpikkert! You have done some great work here, and fast too. I wouldn’t think the shaggy top of the peak would cause problems, but there are problems so that might be it. I was expecting to see a spike up to 5 volts so now I am confused even more. (But understanding comes from confusion, right?)

Perhaps I will need to add circuitry to provide a clean pulse. I’m on a week long road trip, so I’ll have some time to think about it before going back to the ‘lab’.

Thanks again for your quick and very useful data! And the debugging too. :slight_smile:

2 Likes