Code for encoder control of stepper motor speed

Discussion in 'Programmer's Corner' started by SPQR, Nov 23, 2011.

  1. SPQR

    Thread Starter Member

    Nov 4, 2011
    Hello all, simple question for the experts.

    I'm building a camera slider for a friend. It will consist of a simple aluminum frame, two 1/2" rods with linear bearings, and a central ACME threaded rod connected to a Vexta stepper. Control of the motor will be via an Interinar driver and an Arduino.

    The speed control needs to have "bounds" (no slower than X, not faster than Y), but also incremental steps that are programmable.
    I first looked at quadrature encoders, but couldn't really hack the code "simply' so abandoned them.
    I'm not much for using a standard potentiometer because it's analog, and I'm concerned about programming to a resistance that might "drift" over time.
    THEN! I learned about "absolute binary rotary encoders" - and fell in love!
    After a few missteps, I finally got it working and it is fantastic!
    Sixteen steps, output clear, easy to understand - and binary - a four bit code. I agonized a bit about how to convert the four bit binary output from the encoder into a series of "speeds" but then used a brute-force method as follows:
    For each stepper motor interval ( void loop () ), the code reads the encoder and converts the four bits into a speed (time between steps).

    int Pin1 = digitalRead(Encoder_PIN_1); // read all four pins
    int Pin2 = digitalRead(Encoder_PIN_2);
    int Pin3 = digitalRead(Encoder_PIN_3);
    int Pin4 = digitalRead(Encoder_PIN_4);
    RotationSpeed = 300 + (55*((Pin4*8) + (Pin3*4) + (Pin2*2) + Pin1));

    //300 = a controllable variable that is the shortest step - fastest speed
    // 55 = a controllable variable that varies step intervals - the "slope" of the normalization line
    // the rest of the code is just to convert four bits into decimal 0 to 15

    for (int i=0; i < 200; i++)
    digitalWrite(STEP_PIN, HIGH);
    delayMicroseconds(RotationSpeed); // step the motor at calculated speed
    digitalWrite(STEP_PIN, LOW);
    delayMicroseconds(RotationSpeed); // step the motor at calculated speed

    Now the question(s):

    I've used "brute force" to get it to work.
    Are there other, more elegant, more "standard" ways of taking X digital inputs and converting them to a "continuous" variable?
    Look up tables?
    Simple "if then statements"?

    I'm not looking for anyone to write code (I'd rather do that myself so I can learn),
    but rather if you might make some suggestions or point me in the right direction.

    I thank you in advance!
  2. thatoneguy

    AAC Fanatic!

    Feb 19, 2009
    Shifting left is the same as multiplying by 2.

    So x<<4 is the same as x*8

    If you shift bits on temp variables, then AND them into a single variable, the multiplcation can then be carried out.

    Since you are using a 16 bit number (>255), there aren't any other shortcuts for what you are doing.

    I'm fully up how Arduino does bitwise, though I suspect it is similar to the above (Like C), so there should be an example somewhere that shows how to convert your statement to faster binary shifts.

    There are also more efficient functions to get the pin states instead of digitalwrite and digitalread, using direct access to the ports.
  3. SPQR

    Thread Starter Member

    Nov 4, 2011
    Thanks very, very much!

    I found THIS page for "<<" in Arduino C, and THIS page for binary calculations - I was hoping that I could do something using binary.

    Apparently it's fairly complex to have direct control of the ports in the Arduino hardware, but I'll play a little and see what I can do.

    And because of your signature line, I can now do 2^0, 2^1, 2^2, etc.
    Thanks again!!