Stepper Motor Spinning Slow

Posted on
Page
of 2
/ 2
Next
  • Hello,

    I'm using this code to run my step motor :

    var step = 0;
    var steps = [0b0001,0b0010,0b0100,0b1000];
    var stepperPins = [A3,A2,B10,B11]; // Change these to pins for your motor driver
    
    function doStep() {
     step++;
     digitalWrite(stepperPins, steps[step % steps.length]);
    }
    var stepInterval = setInterval(doStep, 200);
    

    I'm using 28BYJ-48 – 5V stepper motor and controller : http://robocraft.ru/files/datasheet/28BY­J-48.pdf

    But it works so slow, approximately 0.5RPM. When I set interval to 30ms it is a little bit faster, but approximately 1RPM. I have tried with 5V and 9V input.

    What I am doing wrong?

  • Does it 'judder' backwards and forwards a bit? It could be the order of the pins is wrong.

    It is also geared, so you'd expect it to run quite slowly

  • it is juddering, it only goes to forward never comes back. I think orders are correct.
    I can see all leds are blinking one by one, in sequence. I think this means that stepper motor wired up correctly.

    It doesn't plugged to a gear, it is working freely.

  • Hi, I think that if anything, the fact that the LEDs blink in sequence probably means that it's wrong.

    See this picture

    So that picture shows 1,2,3,4 in sequence - but if you compare that with your datasheet the order of the coils is different. In yours, and in most steppers, opposing sides are right next to each other so the order should most likely be 1,3,2,4 instead.

    And it isn't connected to a gear, but there is a 64:1 gear inside it. That's why the shaft doesn't come out of the middle.

  • Thanks for your answer @Gordon
    I have wired it up like this

    Stepper Pin 1-D1
    Stepper Pin 2-D2
    Stepper Pin 3-D3
    Stepper Pin 4-D4

    My new code is below, I'm changing the sequence by code

    var step = 0;
    var targetStep = 0;
    var steps = [0b0001,0b0010,0b0100,0b1000];
    var stepperPins = [D1,D3,D2,D4];
    
    function doStep() {
     step++;
     digitalWrite(stepperPins, steps[step % steps.length]);
    }
    var stepInterval = setInterval(doStep, 100);
    

    Now leds blinking in 1-3-2-4 sequence, but now it is juddering back-forward with very very small and quick steps. It is not forwarding any more.

    Also, I have forgot to tell; I'm using ULN2003 driver that shown here : http://www.instructables.com/id/BYJ48-St­epper-Motor/

    Addition :
    This step motor works really fast, please check this video. Stepper in the video works 20 times faster than mine. The same stepper and driver I have.
    http://www.youtube.com/watch?v=KPR1Zt37G­PE

  • Think you got your sequence a bit wring is it not more like described here.

    http://www.geeetech.com/wiki/index.php/S­tepper_Motor_5V_4-Phase_5-Wire_%26_ULN20­03_Driver_Board_for_Arduino

  • Hi @russdx,

    As you pointed; I have converted the code to javascript.at the end It worked great :)
    Here is what I have done

    
    var Pin0 = D1;
    var Pin1 = D2;
    var Pin2 = D3;
    var Pin3 = D4;
    var _step = 0;
    var boolean=true;
    var dir = true;
    
    function setup() 
    { 
     pinMode(Pin0, OUTPUT);  
     pinMode(Pin1, OUTPUT);  
     pinMode(Pin2, OUTPUT);  
     pinMode(Pin3, OUTPUT);  
    }
    
    function loop() 
    { 
     switch(_step){ 
       case 0: 
         digitalWrite(Pin0, LOW);  
         digitalWrite(Pin1, LOW); 
         digitalWrite(Pin2, LOW); 
         digitalWrite(Pin3, HIGH); 
       break;  
       case 1: 
         digitalWrite(Pin0, LOW);  
         digitalWrite(Pin1, LOW); 
         digitalWrite(Pin2, HIGH); 
         digitalWrite(Pin3, HIGH); 
       break;  
       case 2: 
         digitalWrite(Pin0, LOW);  
         digitalWrite(Pin1, LOW); 
         digitalWrite(Pin2, HIGH); 
         digitalWrite(Pin3, LOW); 
       break;  
       case 3: 
         digitalWrite(Pin0, LOW);  
         digitalWrite(Pin1, HIGH); 
         digitalWrite(Pin2, HIGH); 
         digitalWrite(Pin3, LOW); 
       break;  
       case 4: 
         digitalWrite(Pin0, LOW);  
         digitalWrite(Pin1, HIGH); 
         digitalWrite(Pin2, LOW); 
         digitalWrite(Pin3, LOW); 
       break;  
       case 5: 
         digitalWrite(Pin0, HIGH);  
         digitalWrite(Pin1, HIGH); 
         digitalWrite(Pin2, LOW); 
         digitalWrite(Pin3, LOW); 
       break;  
         case 6: 
         digitalWrite(Pin0, HIGH);  
         digitalWrite(Pin1, LOW); 
         digitalWrite(Pin2, LOW); 
         digitalWrite(Pin3, LOW); 
       break;  
       case 7: 
         digitalWrite(Pin0, HIGH);  
         digitalWrite(Pin1, LOW); 
         digitalWrite(Pin2, LOW); 
         digitalWrite(Pin3, HIGH); 
       break;  
       default: 
         digitalWrite(Pin0, LOW); 
         digitalWrite(Pin1, LOW);
         digitalWrite(Pin2, LOW); 
         digitalWrite(Pin3, LOW); 
       break;  
     } 
     if(dir){ 
       _step++; 
     }else{ 
       _step--; 
     } 
     if(_step>7){ 
       _step=0; 
     } 
     if(_step<0){ 
       _step=7; 
     } 
    }
    setup();
    var stepInterdal = setInterval(loop, 1);
    
    
  • But I would want to understand why the code below doesn't work?It is expected to do same think but not.

    var step = 0;
    var steps = [0b0001,0b0011,0b0010,0b0110,0b0100,0b11­00,0b1000,0b1001];
    var stepperPins = [D1,D2,D3,D4]; // Change these to pins for your motor driver
    
    function doStep() {
     step++;
     digitalWrite(stepperPins, steps[step % steps.length]);
    }
    var stepInterval = setInterval(doStep, 1);
    
  • Hm, I don't see why that doesn't work - it should, and is a much more efficient way to do it in Espruino.

    Does this work? (this is more efficient than how you're doing it, but not as good as how you had it, which I think should work.

    var step = 0;
    pinMode(D1,'output');
    pinMode(D2,'output');
    pinMode(D3,'output');
    pinMode(D4,'output');
    var steps = [0b0001,0b0011,0b0010,0b0110,0b0100,0b11­00,0b1000,0b1001];
    var stepperPins = [D1,D2,D3,D4]; // Change these to pins for your motor driver
    function doStep() {
     step++;
    console.log("doing step:"..step);
     //digitalWrite(stepperPins, steps[step % steps.length]);
    var stepval=steps[step % steps.length];
    console.log(stepval);
    digitalWrite(stepperPins[0],stepval&1);
    digitalWrite(stepperPins[1],stepval&2);
    digitalWrite(stepperPins[2],stepval&4);
    digitalWrite(stepperPins[3],stepval&8);
    }
    var stepInterval = setInterval(doStep, 1);
    

    Also, what board are you using that has pins D1-D4 broken out? Most of them don't have port D available. Have you verified that the board is generally working, particularly that time is running at the right speed on it?

  • @fobus, I see your aching... I cannot see any logical difference either... btw, do you have means to record the signals you send to the pins?

    It seems to me also a bit short to just send a 1[ms] pulse... I do not know the spec of the stepper, but a stepper has a mass... and that mass has to be moved... I recall the old days where hard drive arms (of cheaper hard disk and floppy drives) were driven by steppers... and the step frequency at begin and end and also the hold time after reaching the position mattered to actually get the motor rotor to the place where the driver electronic wanted. After all it is just physics... first the 'plain' masses, and then even the electron-masses (changing the (eletro)magnetic fields - gives you phase effects): try to do it slower... start with higher value in setInterval, and speed it up until it does not behave clean anymore. It still does not really explain why the transcribe code works and your's not, because the transcribed code uses the same 1[ms] for stepping. Could it be that there is not enough power supplied to the stepper driver (board)?

    If I'm totally off, let me know and 'edit' the post... ;-)

  • I have worked with UK fruit machine (slot machines to the Americans :D) reels before and they are driven using stepper Motors like allObjects has mentioned they need a ramp up and down tables or the motor will just jump. But using a geared one shouldn't need this? (Fruit machines drive a 12inch reel drum directly)

  • I can't see any difference either... @DrAzzy the pinMode isn't needed in your code - but I'd be interested to see if that makes any difference. It shouldn't :)

    I wonder whether the reason the 'new' code works is that it executes really slowly, and the 1kHz update rate that was requested can't be made.

    What have you connected the power input on your driver board to? It may be that you don't have a high enough voltage available to turn the stepper as fast as you want to?

    It's interesting that in your video, when the stepper motor stops, 3 of the 4 LEDs are on (which I would have said was wrong as that presumably means 3 coils are on - although it does seem to work). Is that the case for you, or is it just 1 or 2 of 4?

    @russdx I think it depends on the mass of the rotor and speed you're trying to get to. When I've used bigger ones I've been able to instantly start and stop at a certain speed, but if I wanted to go very fast I had to ramp the speed up and down.

  • fruit machines...

    ...what a cool disguise for a non-English native! ;)

  • @fobus, take a look at Step motor basics, I found it googling for 'frequency limit of stepper motor momentum'. I'm adding a print in pdf to prevent broken link on link change. PS: have no relations what so ever to http://www.geckodrive.com other than positive affinity due to the fact that geckodrive is no only selling (for $) but also educating (for FREE)... ;-)

    Is it possible that you may have a dud?

    You may find out - but also what type of internal implementation it is at 5 wire stepper.


    1 Attachment

  • Hello,

    There is many questions, I'm sorry if I forgot to answer anyone.

    At first, all 3 code work. The first code that write at the start of this thread works so slow.
    The second one (http://forum.espruino.com/comments/12041­929/) works good bot not fast as @DrAzzy's code (http://forum.espruino.com/comments/12042­026/)
    @DrAzzy code is the fastest (Apx. 13 RPM) When I use this code leds are not blinking in sequence any more. Leds allways on.

    I think that I'm wiring up correctly.

    I'm using stm32F4DISCOVERY. I'm using my boards power supply(5+), today I'm going to try with +9 Volt external battery and write results here.

    I have catched an interesting point.
    @DrAzzy's code works good but only with console.log("doing step:"+step); line.
    When I comment out this line it doesn't work :)

    Also, when I flash the code -with save()- in to the device and restart it @DrAzzy's code doesn't works. It's about console.log() command. I think console.log() command doesn't work if device is working stanalone.

    So, I thought that it needs to wait a little bit before doing next step, here is my new code works good without comments and after save()

    var step = 0;
    pinMode(D1,'output');
    pinMode(D2,'output');
    pinMode(D3,'output');
    pinMode(D4,'output');
    var steps = [0b0001,0b0011,0b0010,0b0110,0b0100,0b11­00,0b1000,0b1001];
    var stepperPins = [D4,D3,D2,D1]; // Change these to pins for your motor driver
    function doStep() {
     step++;
      i=0;
      while(i!=3)i++; //delay a little bit before doing steps. Better than console.log()
    var stepval=steps[step % steps.length];
    digitalWrite(stepperPins[0],stepval&1);
    digitalWrite(stepperPins[1],stepval&2);
    digitalWrite(stepperPins[2],stepval&4);
    digitalWrite(stepperPins[3],stepval&8);
    }
    var stepInterval = setInterval(doStep, 1);
    
  • console.log() command doesn't work if device is working stanalone.

    It's in the FAQ/Troubleshooting. It'll work, but only when the device isn't powered from your PC. If it's powered from the PC you need to open a terminal app first.

    it needs to wait a little bit before doing next step

    Instead of adding a delay, just change var stepInterval = setInterval(doStep, 1); to var stepInterval = setInterval(doStep, 2);. Try different numbers to see what works.

    Leds allways on.

    I'd really, really suggest that you try changing the polarity of the signals:

    digitalWrite(stepperPins[0],!(stepval&1)­);
    digitalWrite(stepperPins[1],!(stepval&2)­);
    digitalWrite(stepperPins[2],!(stepval&4)­);
    digitalWrite(stepperPins[3],!(stepval&8)­);
    

    Personally, I think that the motor driver might be inverting the outputs (so 0 is 1 and 1 is 0). That would mean that you spend a lot of time with 3 coils on (two of which will be 'fighting' each other as they're opposite).

  • Hi @Gordon,

    I don't know why, but when I remove the while(i!=3)i++; line stepper stops working. Change interval to 2-3-4 doesn't help. I have tried to change interval from 1 to 100 but no effect.

    Also change polarity didn't do any effect; Leds and motion is the same

    digitalWrite(stepperPins[0],!(stepval&1)­);
    digitalWrite(stepperPins[1],!(stepval&2)­);
    digitalWrite(stepperPins[2],!(stepval&4)­);
    digitalWrite(stepperPins[3],!(stepval&8)­);
    
  • @fobus, your 'initial correct' code - post #8 - works off the bat with about 12..13 rpm (counter clock-wise looking at the spindle)... just as expected... make it two (2)[ms] stepping speed.

    I use pins C6, C7, C8, and C9 - driver board inputs IN1, IN2, IN3, and IN4 - driver output boards A, B, C, and D - motor wires blue, pink, yellow, orange, and red (red on 4.66V driver chip outputs, the others on driver chip outputs.

    I started with stepping speed/interval 1000ms - first so slow without motor to observe the LEDs, especially the overlapping ON / half stepping - and and then with motor. I kept shortening the interval down to 2[ms]. 1[ms] did not work. Since I have no forces applied (yet), I can run it powered by 5V from laptop USB / Board Bat (4.66 Volts at the driver power pin). Will do some more exploring later with separate driver powering and attempt to increase speed... under no and load... and observe the pins at the driver chip with the scope.

  • Dud? right - sadly literally... some are just mechanical duds.

    I got myself a few of these dirt cheap things... and some they hum smoothly, some they 'rattle' - you hear a hum overlaid with another synchronous noise of much lower frequency... at higher speeds (attached sound examples are at 1[ms] stepping interval. The volume of the rattling/touching noise is from placing the an empty open tuna can upside down on top the phone and the motor on top). Hold the motor with its back onto something resonating or your ear, and you will hear it whether your motors are smooth humming runners or guard rail smashing drunken drivers (out of the 5 I got, 2 hum, 2 hit a bit, one is stuck until you give it a twist in the right direction.)

    The rotating magnet is not always centered and therefore touch the poles. Even a very little it touching just slows them down in getting them moving, and due to the construction, the 2nd step after the initial step just pulls the rotor back in the original position... because it did not reach the 2nd step fully when the poles change again.

    Pulling the rotor out you will notice marks where it touches... bending the poles a tiny tiny little bit can solve the issue... but increases the gap and reduces of course the max torque.

    Run them on 5 V first to separate the good from the bad one. Running them on 12 V works - in some way the duds even better when started slower and then sped up, but they get pretty quickly hotter than I like them... on the other hand, they have quite nice torque. For a running motor heat dissipation is probably not work... but in applications with duty cycles, heat dissipation may be manageable.

    Attached is a shot showing the marks on the rotor - exactly at the position you will notice in the touch.mp4 clip, where you actually can her and 'see' where it touches... (stepping interval - stT = 15[ms]). Attached are too additional - just audio - 'clips' with healthy and unhealthy sound.


    4 Attachments

  • Used your code modified and built some stuff around to easily control it with a global command function r(). I chose r for now because I commanding it from the console.

    Function r accepts the stepping interval in milliseconds as argument.
    Special values are 0 and no argument (undefined), which stop the motor or reverse current direction, respectively. For latter, there exists also a global stop() command function.
    Changing direction does not need a stop command, the code manages that by itself. Positive values step clock-wise, negative ones counter clock-wise (looking at the spindle side).

    1. r(1); // the fastest - about 15 rpm - you can go
    2. r(); // reverses direction (after above r(1) it is like issuing r(-1);
    3. r(0); // stops the motor
    4. stop(); // stops the motor as well

    Note that a stop always stops at an even 'position' and switches all driving pins off.

    Code:

    // stPs stepper pins
    // st   step 0..8
    // stT  step Time in milliseconds [ms]
    // stI  step Interval (from setInterval() and for clearInterval()
    // sts  steps 0001,0011,0010,... pin signals
    // stBW sts - steps Backwards
    // stFW sts - steps Forward
    // dmy  ...because of (cond) ? exprT : exprF needs something to assign to
    var run = false;
    var st = 0;
    var stT = 0;
    var stI = null;
    var sts = null;
    var stSt =  0b0000;
    var stFW = [0b1000,0b1100,0b0100,0b0110,0b0010,0b00­11,0b0001,0b1001];
    var stBW = [0b0001,0b0011,0b0010,0b0110,0b0100,0b11­00,0b1000,0b1001];
    var stPs = [C6,C7,C8,C9];
    
    // setI setInterval(i,stsC) i in [ms] with (optionl) step Change (if not null), 
    // and direction info (string)
    var setI = function(t,stsN,d) {
      console.log("t = ",t, d); 
      if (stI) clearInterval(stI);
      if (stsN) sts = stsN;
      run = true;
      stI = setInterval(stp,t);
    };
    
    // stp step
    var stp = function() { digitalWrite(stPs, sts[st = ++st % 8]); };
    
    // _sFW step ForWard
    var _sFW = function(t) {
      console.log("FW w/ " + t);
      if (stT > 0) { setI((stT = t),null," ~F");
      } else { if (stT) { stop(); } st--; setI((stT = t),stFW," FW"); }
    };
    
    // _sBW step BackWards
    var _sBW = function(t) {
      console.log("BW w/ " + t);
      if (stT < 0) { setI(-(stT = t),null," ~B"); 
      } else { if (stT) { stop(); } st++; setI(-(stT = t),stBW," BW"); }
    };
    
    // stop
    var stop = function() {
      console.log("stop");
      if (stI) { stI = clearInterval(stI); }
      console.log(stI);
      run = false;
      digitalWrite(stPs, stSt);
    };
    
    
    // run function - t is stepping interval in [ms]
    var r = function(t) {  
      if (typeof t === "undefined" ) {
        if (stT) {
          console.log((stT > 0) ? "F>B" : "B>F");
          r(-stT);
        } else {
          console.log("What ?");
        }
      } else { 
        dmy = (t) ? (t>0) ? _sFW(t) : _sBW(t) : stop(); 
      }
    };
    

    To get to to higher speeds, a different approach then setInterval() has to be taken. In order not to hog the Espruino just for the stepper, an interrupt driven stepping in assembler needs to be implemented to get to shorter pulses.

    Attached clip shows 2 seconds fastest forward r(1);, then for same time and same speed reverse r();, then 5 seconds slower forward r(6);, and finally stop stop();

    The 2 seconds ticking you hear in the background comes from a digital clock standing close by... ;-)

    Console:

    >r(1); setTimeout(function(){r(); setTimeout(function(){ r(6); setTimeout(function(){ stop(); },5000); },2000); },2000);
    FW w/ 1
    t =  1  FW
    =2
    F>B
    BW w/ -1
    stop
    t =  1  BW
    FW w/ 6
    stop
    t =  6  FW
    stop
    >
    

    2 Attachments

  • Thanks! It's really interesting to see that some of the motors really are slightly broken.

  • We know that software is never bug free... but it is of great relieve - I'm sure for @fobus - that hardware isn't perfect either... ;-) and the scope where to find the cause for an issues has to include that.

    @fobus' key element is the setup for this extremely terse version of interval callback (paraphrased from stp):

    // stp - step
    var step = function() { digitalWrite(pins,  steps[ stepIdx = ++stepIdx % 8 ]); };
    
  • First thanks all, at the end I could drive it normally. Here is my code

    var step = 0;
    var steps = [0b0001,0b0011,0b0010,0b0110,0b0100,0b11­00,0b1000,0b1001];
    var stepperPins = [E13,E11,E9,E7]; // Change these to pins for your motor driver
    function doStep() {
     step++;
     digitalWrite(stepperPins, steps[step % steps.length]);
    }
    
    function stop(){
      digitalWrite(stepperPins[0],LOW);
      digitalWrite(stepperPins[1],LOW);
      digitalWrite(stepperPins[2],LOW);
      digitalWrite(stepperPins[3],LOW);
    }
    
    function go(f) {
      for (i=0;i<f;i++) {
        x=0;
        while (x<10) x++;//Delaying needed I don't know why.
        doStep();
      }
      stop();
    }
    

    Can you explain me please how much degrees does the motor moves for each doStep() call?
    I think it must move 5.625° for each doStep() but it is not, may be it is 32 time less than 5.625°.

    Also, I have tried both 5V and 9V , 9V has a great torque. 5V some times unable to start spinning, torque is not hight.

  • The data sheet of the stepper motor tells you about the angle per step. If you thought have a geared one, you have to take this in account as well. I figured it out by taping a toth pick at its end to the drive shaft and something similar on something on the desk. I did then run at slow interval and counted. You can also make a console output with the steps run. You repeat with the countex steps to verify. If your motor is not moving, you may step too fast and/or your motor may have some mechanical issues as two out of my five (cheap) ones had. Check m posts in this thread.

    Btw , for stop just create a step with all zeroes 0b000 and out this the same way as you do a step. You do not need to talk to each pin separately. For reference take a look at the code I attached in the post where I discuss my solution.

    There is really good youtube

    out there that explains just everything in very detail. Most important are the 3 modes to operate this motor (shown in the attached picture). I used the half step mode to get decent torque and maximum precision / smoothness. With full stepping, maximum torque is achieved with decent precision, and with that most unlikely to 'loose' or 'slip' a step.


    1 Attachment

    • stepperModes.png
  • Yes, I have counted it step by step. In order to get a full tour I need to call doStep() 512 times . This motors stride angel is 64, so it is mutliplied by 8.

    Thank all again, I have made it work with your helps.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Stepper Motor Spinning Slow

Posted by Avatar for fobus @fobus

Actions