Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 2 of 2

Thread: 256 microstepping example for stepper motors

  1. #1
    Senior Member
    Join Date
    Oct 2012
    Location
    Portland OR
    Posts
    633

    256 microstepping example for stepper motors

    I don't know if anyone has posted similar code, probably they have and I just haven't seen it. So this is mostly just a note to myself, because I find stuff easier here than on my own hard drive.

    This code is for Teensy 3/3.1. It uses 1/256 microstepping with 4 channels of PWM to smoothly drive a 5-wire stepper such as the 28BYJ-48 geared stepper together with ULN2003 driver board (about $3 on ebay). If you try it, note the driver board wants the 4 signals connected as 1,3,2,4 instead of 1,2,3,4 as you might expect.

    Microstepping doesn't necessarily give you better resolution, due to backlash and torque-dependent offset, but it does give you smoother and quieter motion, particularly at slow speeds, than the usual approach like http://forum.pjrc.com/threads/25526-...light=28BYJ-48

    Code:
    // test PWM output on T3.1
    // see also: http://www.pjrc.com/teensy/td_pulse.html
    // J.Beale 9 Aug. 2014
    
    #define CH1 3  // PWM pin channel 1
    #define CH2 4  // PWM pin channel 2
    #define CH3 5  // PWM pin channel 3
    #define CH4 6  // PWM pin channel 4
    #define PI (3.1415926535897932384626433832795)  // only slightly excessive
    
    #define PWMRES (10)  // bits of PWM resolution
    #define MAXPWM (1023) // maximum PWM value
    #define ABINS (256)  // # of lines in sine lookup table
    #define LCMAX (5000) // # of full cycles until we reverse direction
    #define LED1 13  // digital output with LED
    #define SMIN (1.0/200)  // minimum speed
    #define  SMAX (1.0/20)  // maximum speed
    #define TSTEP (150)    // time in msec between changes in speed
    
    short int SINE_TABLE[ABINS];  // sine lookup table
    float sinc;  // time delay increment
    float spd, dly;
    long lcount;  // loop count (number of full cycles of 2*pi)
    int minima;  // how many minimum-speed moments have we passed through?
    boolean rev;  // true when we are running in reverse
    unsigned long tnow, tlast;
    
    void setup() {
      
      digitalWrite(LED1,0);
      analogWriteResolution(PWMRES);
      analogWriteFrequency(CH1, 46875);  // ideal PWM freq for 10 bits, CPU @ 48MHz
      analogWriteFrequency(CH3, 46875);  // ideal PWM freq for 10 bits, CPU @ 48MHz
      pinMode(LED1, OUTPUT);    // enable LED as output
      
      for (int i=0; i<ABINS; i++) {  // wastefully save full 2*pi rather than just pi/2
        float omega = i*2*PI / ABINS;  
        SINE_TABLE[i] = MAXPWM * sin(omega);
      }
      
      sinc = 1.1;  // factor for increment in speed
      spd = 1/50.0; // actual speed  
      lcount = 0;
      minima = 0;
      rev = false;
      tlast = millis();
    } // end setup
    
    
    void loop() {
      
    short int A,B,C,D;  // PWM setting values  
    float omega;  // current angle in radians
    float delta;  // stepsize for omega
    int k;
    
      digitalWrite(LED1, !rev);  // indicate if we are in fwd
      lcount++;
    
      tnow = millis();
      if ((tnow - tlast) > TSTEP) {  // time now for a change in speed?
        spd *= sinc;
        tlast = tnow;
        if (spd > SMAX) {  // if now above max speed, start decreasing it
          spd = SMAX; 
          sinc = 1/sinc;  
        }
        if (spd < SMIN) {  // if now below minimum speed, start increasing it
            sinc = 1/sinc;
            spd = SMIN;
            minima++;
            if ((minima > 2)) { // every so often, change direction of rotation
              minima = 0;
              rev = !rev; 
          }
        } 
      }
      
      dly = 1/spd;  // delay time is inverse of speed
      for (int i=0; i<ABINS; i++) {  // do one full cycle of 2pi radians
        delayMicroseconds(dly);
        int ci = i + ABINS/4;
        if (ci >= ABINS) ci = ci - ABINS;
    
        // are we now going in reverse?
        if (rev == true) k = (ABINS-1) - i; else  k = i; 
        
        A = SINE_TABLE[k];
        C = SINE_TABLE[ci];
        if (A > 0) B=0; else { B = -A; A = 0; }  // H-bridge: negative means use 2nd channel 
        if (C > 0) D=0; else { D = -C; C = 0; }
    
        analogWrite(CH1,A); // update the PWM duty cycle value
        analogWrite(CH2,B); // on each of the four outputs...
        analogWrite(CH3,C); // 
        analogWrite(CH4,D); // 
      }
    } // end loop()
    Last edited by JBeale; 08-10-2014 at 12:58 AM.

  2. #2
    Quote Originally Posted by JBeale View Post
    Code:
      ...
      analogWriteFrequency(CH1, 46875);  // ideal PWM freq for 10 bits, CPU @ 48MHz
      analogWriteFrequency(CH3, 46875);  // ideal PWM freq for 10 bits, CPU @ 48MHz
      ...
    Hello, JBeale.

    Thank you for such a good solution.

    I am just bit worried if I have Teensy 3.1(2) should I put here a 70312 or something?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •